# coding=UTF-8
import calendar
import multiprocessing
import os
import re
import sys
import time
import winreg
from datetime import datetime, timedelta
from threading import Thread

import pandas as pd
import pyautogui
import requests
from PyQt5 import QtGui
from PyQt5.QtCore import QRegExp, QSortFilterProxyModel, QTimer, Qt, pyqtSignal
from PyQt5.QtGui import QBrush, QPixmap, QRegExpValidator
from PyQt5.QtWidgets import QApplication, QCompleter, QHeaderView, QInputDialog, QMainWindow, \
    QMessageBox, \
    QStyleFactory, QTableWidgetItem, QTreeWidgetItem, QTreeWidgetItemIterator, qApp
from bs4 import BeautifulSoup
from dateutil.parser import parse

import 工具类
import 模块包.主窗口
import 模块包.出口下货纸
import 模块包.动态大类维护
import 模块包.动态类型维护
import 模块包.场站维护
import 模块包.外点返场
import 模块包.多样查询
import 模块包.客户维护
import 模块包.尺寸维护
import 模块包.属性设置
import 模块包.拖车类型维护
import 模块包.最近船期
import 模块包.权限设置
import 模块包.测试
import 模块包.用户管理
import 模块包.登录窗口
import 模块包.笔趣阁小说
import 模块包.箱型维护
import 模块包.箱属维护
import 模块包.综合查询
import 模块包.航次维护
import 模块包.船名维护
import 模块包.船期查询
import 模块包.补工作证
import 模块包.表格改造
import 模块包.计件统计
import 模块包.费目维护
import 模块包.超级管理员维护表
import 模块包.车队维护
import 模块包.酷狗音乐
import 模块包.集港出场
import 模块包.集港时间
from 工具类 import 网络连接, 托盘, 数据库_mysql


class 用户维护(工具类.管理基类, 模块包.用户管理.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__('用户维护', 'yonghu', 父窗口)


class 场站维护(工具类.管理基类, 模块包.场站维护.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__('场站维护', 'changzhan', 父窗口)


class 船名维护(工具类.管理基类, 模块包.船名维护.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__('船名维护', 'chuanboziliao', 父窗口)


class 车队维护(工具类.管理基类, 模块包.车队维护.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__('车队维护', 'chedui', 父窗口)


class 费目维护(工具类.管理基类, 模块包.费目维护.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__('费目维护', 'feimu', 父窗口)


class 客户维护(工具类.管理基类, 模块包.客户维护.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__('客户维护', 'kehu', 父窗口)


class 动态大类维护(工具类.管理基类, 模块包.动态大类维护.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__('动态大类维护', 'dongtaidalei', 父窗口)


class 动态类型维护(工具类.管理基类, 模块包.动态类型维护.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__('动态类型维护', 'dongtaileixng', 父窗口)


class 拖车类型维护(工具类.管理基类, 模块包.拖车类型维护.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__('拖车类型维护', 'tuocheleixing', 父窗口)


class 箱型维护(工具类.管理基类, 模块包.箱型维护.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__('箱型维护', 'xiangxing', 父窗口)


class 尺寸维护(工具类.管理基类, 模块包.尺寸维护.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__('尺寸维护', 'chicun', 父窗口)


class 箱属维护(工具类.管理基类, 模块包.箱属维护.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__('箱属维护', 'xiangshu', 父窗口)


class 航次维护(工具类.管理基类, 模块包.航次维护.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__(' 航次维护', 'hangci', 父窗口)


class 超级管理员维护(工具类.管理基类, 模块包.超级管理员维护表.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super().__init__('超级管理员维护', 'yonghu', 父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.组件设置()
        self.事件绑定()

    def 组件设置(self):
        try:
            self.comboBox.addItems([""] + self.父窗口.数据库.获取所有表名())
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            self.comboBox.currentTextChanged.connect(self.qiehuan)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 外点返场(QMainWindow, 模块包.外点返场.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super(外点返场, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.数据库 = 父窗口.数据库 if 父窗口 else 数据库_mysql()
        self.网络 = 父窗口.网络 if 父窗口 else 网络连接()
        self.组件设计()
        self.事件绑定()

    def 组件设计(self):
        pass

    def 事件绑定(self):
        pass


class 集港出场(QMainWindow, 模块包.集港出场.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super(集港出场, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.数据库 = 父窗口.数据库 if 父窗口 else 数据库_mysql()
        self.网络 = 父窗口.网络 if 父窗口 else 网络连接()
        self.组件设计()
        self.事件绑定()

    def 组件设计(self):
        pass

    def 事件绑定(self):
        pass


class 出口下货纸(QMainWindow, 模块包.出口下货纸.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super(出口下货纸, self).__init__(父窗口)
            self.setupUi(self)

        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.数据库 = 父窗口.数据库 if 父窗口 else 数据库_mysql()
        self.网络 = 父窗口.网络 if 父窗口 else 网络连接()

        self.组件设计()
        self.事件绑定()

    def 组件设计(self):
        pass

    def 事件绑定(self):
        pass


class 属性设置(工具类.管理基类, 模块包.属性设置.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        super().__init__('属性设置', 'zhuti', 父窗口)

    def 事件绑定(self):
        try:
            self.pushButton_yingyong.clicked.connect(self.yingyong)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def yingyong(self):
        try:
            self.父窗口.属性配置()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 多样查询(QMainWindow, 模块包.多样查询.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super(多样查询, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.数据库 = 父窗口.数据库 if 父窗口 else 数据库_mysql()
        self.网络 = 父窗口.网络 if 父窗口 else 网络连接()
        self.根目录 = None
        self.组件设置()
        self.事件绑定()

    def 组件设置(self):
        try:
            self.statusbar.showMessage("多样查询", 2000)
            self.treeWidget.setColumnCount(工具类.常量.多样查询_栏数)  # 设定栏数
            self.treeWidget.setColumnWidth(0, 工具类.常量.多样查询_第一栏宽)  # 设置列宽
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            # 编辑框内容改变，小写改成大写
            self.lineEdit_xh.textEdited.connect(self.bjknrgb)
            # 添加单箱查询按钮点击事件
            self.pushButton_dxcx.clicked.connect(self.dxcx)
            # 添加整船查询按钮点击事件
            self.pushButton_zccx.clicked.connect(self.zccx)

            # 添加by按钮点击事件
            self.pushButton_by.clicked.connect(self.by)
            # 添加qk按钮点击事件
            self.pushButton_qk.clicked.connect(self.qingkong)

            # 添加树形框点击事件
            self.treeWidget.clicked.connect(self.Tree_Clicked)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 生成树(self, 参数, 根目录):
        try:
            if isinstance(参数, dict):
                for key, value in 参数.items():
                    child_node = QTreeWidgetItem(根目录)
                    child_node.setText(0, key)
                    if isinstance(value, (str, int)):
                        child_node.setText(1, str(value))
                    else:
                        self.生成树(value, child_node)
            elif isinstance(参数, list):
                for item in 参数:
                    if isinstance(item, (str, int)):
                        根目录.setText(1, str(item))
                    else:
                        self.生成树(item, 根目录)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def Tree_Clicked(self, 项目索引):
        try:
            # print(self.sender().currentItem().text(0))  # 获取点击的key的值
            # print(self.sender().currentItem().text(1))  # 获取点击的value的值

            # print(项目索引.data())  # 和上面两句相等

            self.statusbar.showMessage(项目索引.data(), 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def dxcx(self):
        try:
            self.qingkong()
            箱号 = self.lineEdit_xh.text()
            if self.父窗口.登陆状态 and len(箱号) == 11:
                try:
                    返回信息 = self.网络.单箱查询(箱号)
                    self.根目录 = QTreeWidgetItem(self.treeWidget)
                    self.根目录.setText(0, 箱号 + '单箱查询')
                    self.treeWidget.setStyle(QStyleFactory.create("windows"))
                    self.生成树(返回信息, self.根目录)
                    self.单箱操作节点('DQZTMC')
                    self.statusbar.showMessage(箱号 + '单箱查询', 2000)
                except Exception as e:
                    工具类.logger.exception(f"单箱查询失败: {e}")
                    self.statusbar.showMessage("单箱查询失败", 2000)
            else:
                self.statusbar.showMessage("运港通尚未登录,或箱号不是11位", 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def zccx(self):
        try:
            self.qingkong()
            箱号 = self.lineEdit_xh.text()
            if self.父窗口.登陆状态 and len(箱号) == 11:
                try:
                    返回信息 = self.网络.装箱单(箱号)
                    返回信息 = 返回信息['数据'][0]
                    需要查询信息 = {
                        'searchMap[cmhc]': 返回信息['船名代码'] + 返回信息['航次'],
                        'searchMap[MTMC]': 返回信息['码头'][:-2],
                        'searchMap[ZWCM]': 返回信息['中文船名']
                    }
                    返回信息 = self.网络.场站整船查询(cmhc=需要查询信息['searchMap[cmhc]'],
                                          MTMC=需要查询信息['searchMap[MTMC]'],
                                          ZWCM=需要查询信息['searchMap[ZWCM]'])
                    self.根目录 = QTreeWidgetItem(self.treeWidget)
                    self.根目录.setText(0, 箱号 + '信息')
                    self.treeWidget.setStyle(QStyleFactory.create("windows"))
                    self.生成树(返回信息, self.根目录)
                    self.整船操作节点(箱号)
                    self.statusbar.showMessage(箱号 + '整船查询', 2000)
                except Exception as e:
                    工具类.logger.exception(f"整船查询失败: {e}")
                    self.statusbar.showMessage("整船查询失败", 2000)
            else:
                self.statusbar.showMessage("运港通尚未登录,或箱号不是11位", 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 单箱操作节点(self, 节点文本):

        try:
            iterator = QTreeWidgetItemIterator(self.treeWidget)
            while iterator.value():
                item = iterator.value()
                if item.text(0) == 节点文本:
                    self.根目录.setText(1, item.text(1))
                    brush_red = QBrush(Qt.yellow)
                    item.setBackground(0, brush_red)
                    brush_blue = QBrush(Qt.yellow)
                    item.setBackground(1, brush_blue)
                    while item.parent() is not None:
                        self.treeWidget.expandItem(item)
                        item = item.parent()
                        self.treeWidget.expandItem(item)
                iterator += 1
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 整船操作节点(self, 节点文本):
        try:
            iterator = QTreeWidgetItemIterator(self.treeWidget)
            while iterator.value():
                item = iterator.value()

                if item.text(0) == 'XH' and item.text(1) == 节点文本:
                    brush_red = QBrush(Qt.yellow)
                    item.setBackground(0, brush_red)
                    brush_blue = QBrush(Qt.yellow)
                    item.setBackground(1, brush_blue)
                    while item.parent() is not None:
                        self.treeWidget.expandItem(item)
                        item = item.parent()
                        self.treeWidget.expandItem(item)
                iterator += 1
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def bjknrgb(self, 编辑框内容):  # 编辑框内容改变
        try:
            self.lineEdit_xh.setText(编辑框内容.upper())
            if len(编辑框内容) == 11:
                # self.chaxun()
                pass





        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def qingkong(self):
        try:
            if self.根目录 is not None:
                self.treeWidget.takeTopLevelItem(self.treeWidget.indexOfTopLevelItem(self.根目录))  # 删除父节点
            self.statusbar.showMessage("清空", 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def by(self):
        try:
            self.statusbar.showMessage("备用", 2000)

        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 模拟操作(QMainWindow, 模块包.酷狗音乐.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super(模拟操作, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.组件设置()
        self.事件绑定()

    def 组件设置(self):
        try:
            self.statusbar.showMessage("模拟操作", 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            # 在当前鼠标位置点击左键
            pyautogui.click()
            # 在 (x, y) 坐标位置点击左键
            pyautogui.click(0, 0)
            # 在 (x, y) 坐标位置点击右键
            pyautogui.rightClick(0, 0)

            # 输入文本字符串
            pyautogui.typewrite('Hello, world!')
            # 按下和释放某个键
            pyautogui.press('enter')
            # 按下和释放多个键
            pyautogui.hotkey('ctrl', 'c')
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 最近船期(工具类.管理基类, 模块包.最近船期.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super().__init__('最近船期', 'zuijinchuanqi', 父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.数据库 = 父窗口.数据库 if 父窗口 else 数据库_mysql()
        self.网络 = 父窗口.网络 if 父窗口 else 网络连接()
        self.组件设置()
        self.事件绑定()

    def 组件设置(self):
        try:
            self.statusbar.showMessage("最近船期", 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            pass
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def shuaxin(self):
        try:
            pass
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        # hangshu = self.tableWidget.rowCount()

        # for i in range(hangshu):
        # 	转换船名 = {'船名代码': self.tableWidget.item(i, 工具类.常量.最近船期_船名代码列号).text(),
        # 	            '中文船名': self.tableWidget.item(i, 工具类.常量.最近船期_中文船名列号).text(),
        # 	            '出口航次': self.tableWidget.item(i, 工具类.常量.最近船期_出口航次列号).text()}
        # 	if self.tableWidget.item(i, 工具类.常量.最近船期_码头列号).text() == '':
        # 		转换船名['码头'] = 'QQCT'
        # 	else:
        # 		转换船名['码头'] = self.tableWidget.item(i, 工具类.常量.最近船期_码头列号).text()
        # 	aaaaa = self.查询船期(转换船名)
        # 	timestamp = int(aaaaa['数据'][:-3])  # 输入要转换的时间戳
        # 	formatted_date = str(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp)))
        #
        # 	单元格 = QTableWidgetItem(str(formatted_date))
        # 	单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        # 	self.tableWidget.setItem(i, 工具类.常量.最近船期_船期列号, 单元格)

        #
        # aaaaa = self.查询船期(转换船名)
        # timestamp = int(aaaaa['数据'][:-3])  # 输入要转换的时间戳
        # formatted_date = str(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp)))

        # self.日志器.info('结束')

    def 查询船期(self, 转换船名):
        try:
            a = self.网络.集装箱船舶计划(转换船名['船名代码'], 转换船名['中文船名'], 转换船名['出口航次'],
                                码头位置=转换船名['码头'])
            返回 = {}
            if a.get('结果', False):

                if a.get('数量', 0) == 0:

                    返回['结果'] = False
                    返回['错误描述'] = '集装箱船舶计划数量=0'

                elif a.get('数量', 1):
                    返回['结果'] = True
                    返回['数据'] = a.get('数据')[0]['预计到港时间']

                else:
                    返回['结果'] = False
                    返回['错误描述'] = '集装箱船舶计划数量大于1'

            else:
                返回['结果'] = False
                返回['错误描述'] = '集装箱船舶计划查询失败'

            return 返回


        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)



class 集港时间(工具类.管理基类, 模块包.集港时间.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super().__init__('集港时间', 'zuijinchuanbojihua', 父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.数据库 = 父窗口.数据库 if 父窗口 else 数据库_mysql()
        self.网络 = 父窗口.网络 if 父窗口 else 网络连接()
        self.过滤条件 = ''
        self.标签箱站 = [self.checkBox_xz1, self.checkBox_xz2, self.checkBox_xz3, self.checkBox_xz4, self.checkBox_xz5,
                     self.checkBox_xz6]
        self.标签码头 = [self.checkBox_23, self.checkBox_4, self.checkBox_5]
        self.合作箱站 = ['不限']
        self.组件设计()
        self.事件绑定()

    def 组件设计(self):
        self.加下拉列表内容()
        try:
            # 正则语句 = QRegExp('[a-zA-Z0-9]+$')  # 建立正则语句
            # 正则验证器 = QRegExpValidator(正则语句, self)  # 实例化正则验证器
            # self.lineEdit_xh.setValidator(正则验证器)  # 绑定正则验证器
            # self.lineEdit_xh.setValidator(正则验证器)  # 绑定正则验证器
            self.合作箱站 = ['不限']
            箱站 = self.数据库.查询数据('changzhan', 字段列表=['场站代码'], 查询条件={'标记状态': '标记'})
            for i in 箱站:
                self.合作箱站.append(i[0])
            # 进度条显示方式：%p-百分比，%v-数值，%m-被总step所取代
            # self.progressBar.setFormat('?/?')
            for i in range(len(self.合作箱站)):
                self.标签箱站[i].setText(self.合作箱站[i])
                self.标签箱站[i].setEnabled(True)

            self.dateTimeEdit_kssj.setDate(datetime.now().date())
            self.dateTimeEdit_jssj.setDate(datetime.now() + timedelta(days=工具类.常量.集港时间_起止相差天数))
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            self.checkBox_23.clicked.connect(self.guolv)
            self.checkBox_4.clicked.connect(self.guolv)
            self.checkBox_5.clicked.connect(self.guolv)

            self.checkBox_xz1.clicked.connect(self.guolv)
            self.checkBox_xz2.clicked.connect(self.guolv)
            self.checkBox_xz3.clicked.connect(self.guolv)
            self.checkBox_xz4.clicked.connect(self.guolv)
            self.checkBox_xz5.clicked.connect(self.guolv)
            self.checkBox_xz6.clicked.connect(self.guolv)

            # self.dateTimeEdit_kssj.editingFinished.connect(self.kssj)
            # self.dateTimeEdit_jssj.editingFinished.connect(self.jssj)
            self.checkBox_qssj.clicked.connect(self.guolv)
            # self.checkBox_cmhc.clicked.connect(self.guolv)
            self.comboBox_cmhc.activated.connect(self.cmhc)

            self.pushButton_shaixuan.clicked.connect(self.guolv)
            self.pushButton_gengxin.clicked.connect(self.gengxin)

        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def kssj(self):
        try:
            if self.checkBox_qssj.isChecked():
                self.guolv()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def jssj(self):
        try:
            if self.checkBox_qssj.isChecked():
                self.guolv()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def cmhc(self):
        try:
            if self.checkBox_cmhc.isChecked():
                过滤条件 = self.生成条件()
                if 过滤条件 == "无条件":
                    self.模型.setFilter('')
                else:
                    self.模型.setFilter(过滤条件)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    # self.美化显示效果()

    def 生成条件(self):
        try:
            条件 = []
            筛选码头 = []
            for i in self.标签码头:
                if i.isChecked():
                    筛选码头.append("'" + i.text() + "'")
            筛选码头条件 = ",".join(筛选码头)
            if len(筛选码头) != 0:
                条件.append("码头 in (" + 筛选码头条件 + ")")

            筛选箱站 = []
            for i in self.标签箱站:
                if i.isChecked():
                    筛选箱站.append("'" + i.text() + "'")
            筛选箱站条件 = ",".join(筛选箱站)
            if len(筛选箱站) != 0:
                条件.append("箱站 in (" + 筛选箱站条件 + ")")

            if self.checkBox_cmhc.isChecked():
                船名航次 = self.comboBox_cmhc.currentText()
                if 船名航次 != "":
                    条件.append(f"船名航次 = '{船名航次}'")

            if self.checkBox_qssj.isChecked():
                开始时间 = self.dateTimeEdit_kssj.dateTime().toString('yyyy-MM-dd hh:mm:ss')
                结束时间 = self.dateTimeEdit_jssj.dateTime().toString('yyyy-MM-dd hh:mm:ss')

                条件.append(f"开始时间 <= str_to_date('{结束时间}', '%Y-%m-%d %H:%i:%s')")
                条件.append(f"结束时间 >= str_to_date('{开始时间}', '%Y-%m-%d %H:%i:%s')")

            if len(条件) != 0:
                过滤条件 = " and ".join(条件)
            else:
                过滤条件 = "无条件"
            return 过滤条件
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def guolv(self):
        try:
            过滤条件 = self.生成条件()
            if 过滤条件 == "无条件":
                self.模型.setFilter('')
            else:
                self.模型.setFilter(过滤条件)
            self.加下拉列表内容()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    # self.美化显示效果()

    def 美化显示效果(self):

        try:
            行数 = self.tableView.model().rowCount()

            列数 = self.tableView.model().columnCount()

            for i in range(行数):
                if self.模型.item(i, 工具类.常量.集港时间_场站列号).text() in self.合作箱站:
                    开始 = self.模型.item(i, 工具类.常量.集港时间_开始列号).text()
                    结束 = self.模型.item(i, 工具类.常量.集港时间_结束列号).text()
                    开始时间 = datetime.strptime(开始, '%Y-%m-%d %H:%M:%S')
                    结束时间 = datetime.strptime(结束, '%Y-%m-%d %H:%M:%S')
                    现在时间 = datetime.now()
                    if 现在时间 < 开始时间:
                        for j in range(列数):
                            self.tableView.item(i, j).setBackground(工具类.常量.集港时间_未来蓝)
                    elif 结束时间 < 现在时间:
                        for j in range(列数):
                            self.tableView.item(i, j).setBackground(工具类.常量.集港时间_无关灰)
                    else:
                        for j in range(列数):
                            self.tableView.item(i, j).setBackground(工具类.常量.集港时间_进行绿)
                else:
                    for j in range(列数):
                        self.tableView.item(i, j).setBackground(工具类.常量.集港时间_无关灰)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 加下拉列表内容(self):
        try:
            船名航次 = ['']

            num = self.模型.rowCount()
            for i in range(num):
                船名航次.append(self.模型.index(i, 3).data())
            船名航次 = list(set(船名航次))
            self.comboBox_cmhc.clear()
            self.comboBox_cmhc.addItems(船名航次)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def gengxin(self):
        try:
            self.最近船舶计划 = self.数据库.查询数据('zuijinchuanbojihua',
                                        字段列表=['码头', '中文船名', '英文船名', '出口航次', '船名代码'])
            self.progressBar.setMaximum(len(self.最近船舶计划))

            线程 = Thread(target=self.更新集港时间数据)
            线程.start()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 更新集港时间数据(self):
        try:
            if not self.父窗口.登陆状态:
                self.statusbar.showMessage('运港通尚未登录！', 2000)
                return
            开始时间 = time.time()
            工具类.logger.exception(f"开始清空集港时间数据")
            self.statusbar.showMessage(f"开始清空集港时间数据", 2000)

            self.数据库.清空数据库表('jigangshijian')

            工具类.logger.exception(f"清空结束，开始更新...")
            self.statusbar.showMessage(f"清空结束，开始更新...", 2000)

            最近船舶计划 = self.数据库.查询数据('zuijinchuanbojihua',
                                   字段列表=['码头', '中文船名', '英文船名', '出口航次', '船名代码'])
            self.progressBar.setMaximum(len(最近船舶计划))
            进度 = 1
            插入数据列表 = []
            for i in self.最近船舶计划:
                if len(i[0]) > 5:
                    码头位置 = i[0][:5]
                else:
                    码头位置 = i[0]
                收箱截货计划列表 = self.网络.收箱截货计划(码头位置, i[1], i[2], i[3], i[4])
                if 收箱截货计划列表.get('结果', False) and 收箱截货计划列表.get('数量', 0) != 0:
                    for 值 in 收箱截货计划列表.get('数据'):
                        船名航次 = 值['船名代码'] + 值['出口航次']
                        插入数据列表.append((值.get('码头', ''), 值.get('中文船名', ''), 船名航次, 值.get('箱站代码', ''),
                                       值.get('空重', ''),
                                       值.get('收箱开始时间', ''), 值.get('收箱结束时间', ''), 值.get('加急标志', ''),
                                       值.get('加急结束时间', ''), 值.get('备注', '')))

                self.progressBar.setValue(进度)
                进度 += 1
            # ['码头', '中文船名', '船名航次', '箱站', '空重', '开始时间', '结束时间', '加急标志', '加急结束时间', '备注']
            self.数据库.插入多条数据('jigangshijian', 插入数据列表)
            self.progressBar.setValue(0)
            结束时间 = time.time()
            self.shuaxin()

            工具类.logger.exception(f"集港时间数据更新成功，耗时：{结束时间 - 开始时间} 秒")
            self.statusbar.showMessage(f"集港时间数据更新成功，耗时：{结束时间 - 开始时间} 秒", 2000)

            工具类.logger.exception(f"集港时间数据更新成功，耗时：{结束时间 - 开始时间} 秒")
            self.statusbar.showMessage(f'更新成功!  耗时：{结束时间 - 开始时间} 秒', 2000)

        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 补工作证(QMainWindow, 模块包.补工作证.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super(补工作证, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.数据 = 工具类.常量.补工作证_初始数据
        self.表头 = 工具类.常量.补工作证_表头
        self.组件设计()
        self.事件绑定()

    def 组件设计(self):
        try:
            self.textEdit.setText(self.数据)
            self.tableWidget_gzz.setColumnCount(len(self.表头))
            self.tableWidget_gzz.setHorizontalHeaderLabels(self.表头)
            self.tableWidget_gzz.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            self.tableWidget_gzz.dragEnterEvent = self.拖拽进来
            self.tableWidget_gzz.dragMoveEvent = self.拖拽移动
            self.tableWidget_gzz.dropEvent = self.拖拽放置

            # self.lineEdit_xxts.dropEvent = self.拖拽放置

            self.tableWidget_gzz.cellPressed.connect(self.salegoodsselect)
            self.pushButton_dayin.clicked.connect(self.dayin)
            self.pushButton_chazhaoxianghao.clicked.connect(self.chazhaoxianghao)
            self.pushButton_dayinyulan.clicked.connect(self.dayinyulan)
            self.pushButton_zidongzairu.clicked.connect(self.zidongzairu)
            self.pushButton_qingkong.clicked.connect(self.qingkong)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 拖拽进来(self, event):  # 拖拽进来
        try:
            if event.mimeData().hasUrls:
                event.accept()
            else:
                event.ignore()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 拖拽移动(self, event):  # 拖拽移动
        try:
            if event.mimeData().hasUrls:
                event.accept()
            else:
                event.ignore()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 拖拽放置(self, event):  # 拖拽放置
        try:
            if event.mimeData().hasUrls:
                event.setDropAction(Qt.CopyAction)
                event.accept()
                links = [url.toLocalFile() for url in event.mimeData().urls()]
                self.statusbar.showMessage(links[0], 2000)
                try:
                    self.全局数据 = pd.read_excel(links[0]).dropna(thresh=5)
                    self.显示()
                except Exception as e:
                    工具类.logger.exception(f"拖拽放置失败: {e}")
                    self.statusbar.showMessage("读取文件失败", 2000)
            else:
                event.ignore()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 显示(self):
        try:
            for i in self.全局数据.values:
                num = self.tableWidget_gzz.rowCount()
                self.tableWidget_gzz.setRowCount(num + 1)  # 添加一行
                for j in range(len(self.表头)):
                    单元格 = QTableWidgetItem(str(i[j]))
                    单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                    self.tableWidget_gzz.setItem(num, j, 单元格)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def salegoodsselect(self, row, col):
        try:
            箱信息 = {self.表头[j]: self.tableWidget_gzz.item(row, j).text() for j in range(len(self.表头))}
            self.生成数据(箱信息)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 生成数据(self, 箱信息):
        try:
            self.数据 = f'''
            			山东捷丰国际储运有限公司
            				入港单/工作证
            		------------------------------
            		船名/航次:{箱信息.get('船名(中)', '海丰恒德')}/{箱信息.get('航次', '2306S')}
            		箱号:{箱信息.get('箱号', 'TGBU2574913')}
            		尺寸/箱型:{箱信息.get('尺寸', '20')}{箱信息.get('箱型', 'GP')}
            		备注:补打工作证
            		------------------------------
            		起始地点:{箱信息.get('起运地点', '捷丰南港重箱')}
            		卸箱地点:{箱信息.get('卸箱地点', 'QQCTU')}
            		单/背:{箱信息.get('入港方式', '单背')}     空重:{箱信息.get('空重', 'F')}
            		箱号:{箱信息.get('箱号', 'TGBU2574913')}
            		车队:{箱信息.get('车队', '元创初心')}
            		车号：{箱信息.get('车号', '鲁UR9520')}
            		工作证号:{箱信息.get('工作证号', 'J20230619000738')}
            		集港时间:{箱信息.get('入港时间', '2023-06-17 22:00：00')}
            		打印时间:{箱信息.get('打印时间', '2023-06-20 07:00:00')}
            		打印人:{箱信息.get('打印人', '盈思佳德1出口')}
            		------------------------------
            		联系电话:前湾80659523
            			港服86058731
            			四期15054295403
            		---------------END------------
            			'''
            self.textEdit.setText(self.数据)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def dayin(self):
        try:
            数据 = self.textEdit.toPlainText()
            工具类.打印数据(数据)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def chazhaoxianghao(self):
        try:
            text = self.lineEdit_gzzhx.text()
            items = self.tableWidget_gzz.findItems(text, Qt.MatchExactly)
            if items:
                item = items[0]
                # item.setBackground(QBrush(QColor(0, 255, 0)))
                # item.setForeground(QBrush(QColor(255, 0, 0)))
                row = item.row()
                # 定位到指定行
                self.tableWidget_gzz.verticalScrollBar().setSliderPosition(row)
                self.tableWidget_gzz.setCurrentCell(row, 0)
                箱信息 = {self.表头[j]: self.tableWidget_gzz.item(row, j).text() for j in range(len(self.表头))}
                self.生成数据(箱信息)
            else:
                self.statusbar.showMessage('没有这个箱号', 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def dayinyulan(self):
        try:
            pass
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def zidongzairu(self):
        try:
            key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
                                 r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders')
            文件名 = winreg.QueryValueEx(key, "Desktop")[0] + '\\补工作证.Xls'

            try:
                self.全局数据 = pd.read_excel(文件名)
            except Exception as e:
                工具类.logger.exception(e)
                self.statusbar.showMessage('打开默认文件失败！', 2000)
            else:
                self.显示()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def qingkong(self):
        try:
            self.tableWidget_gzz.setColumnCount(len(self.表头))
            self.tableWidget_gzz.setRowCount(0)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 表格改造(QMainWindow, 模块包.表格改造.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super(表格改造, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.组件设计()
        self.事件绑定()

    def 组件设计(self):
        try:
            pass
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            self.textBrowser_qqctu.dragEnterEvent = self.拖拽事件_qqctu
            self.textBrowser_qqctu.dragMoveEvent = self.拖拽事件_qqctu
            self.textBrowser_qqctu.dropEvent = self.拖拽放置_qqctu

            self.textBrowser_qqctn.dragEnterEvent = self.拖拽事件_qqctn
            self.textBrowser_qqctn.dragMoveEvent = self.拖拽事件_qqctn
            self.textBrowser_qqctn.dropEvent = self.拖拽放置_qqctn
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 拖拽事件_qqctu(self, event):  # 拖拽进来和拖拽移动
        try:
            if event.mimeData().hasUrls():
                event.accept()
            else:
                event.ignore()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 拖拽放置_qqctu(self, event):  # 拖拽放置
        try:
            if event.mimeData().hasUrls:
                event.setDropAction(Qt.CopyAction)
                event.accept()
                file_path = event.mimeData().urls()[0].toLocalFile()
                self.statusbar.showMessage(file_path, 2000)
                self.表格改造(file_path)
            else:
                event.ignore()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 拖拽事件_qqctn(self, event):  # 拖拽进来和拖拽移动
        try:
            if event.mimeData().hasUrls():
                event.accept()
            else:
                event.ignore()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 拖拽放置_qqctn(self, event):  # 拖拽放置
        try:
            if event.mimeData().hasUrls:
                event.setDropAction(Qt.CopyAction)
                event.accept()
                file_path = event.mimeData().urls()[0].toLocalFile()
                self.statusbar.showMessage(file_path, 2000)
            else:
                event.ignore()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 表格改造(self, 表格文件):
        try:
            self.textBrowser_qqctu.append('改造开始：' + 表格文件 + '...')
            self.textBrowser_qqctu.append('转换表...')
            Excel表格文件 = 工具类.Excel文件(表格文件)
            self.textBrowser_qqctu.append('转换完毕...')
            self.textBrowser_qqctu.append('删除多余列...')

            Excel表格文件.删除('B:C')
            Excel表格文件.删除('C:R')
            Excel表格文件.删除('D:I')
            Excel表格文件.删除('E:M')
            Excel表格文件.删除('F:Z')
            Excel表格文件.删除('G:Y')
            Excel表格文件.删除('H:AF')

            self.textBrowser_qqctu.append('删空完毕...')
            self.textBrowser_qqctu.append('格式设置...')

            Excel表格文件.拆分单元格('H8:H50')
            Excel表格文件.自适应列宽('a:i')

            self.textBrowser_qqctu.append('格式设置完毕...')

            Excel表格文件.保存()

            self.textBrowser_qqctu.append('保存完毕...')
            self.textBrowser_qqctu.append('改造结束。')
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 船期查询(QMainWindow, 模块包.船期查询.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super(船期查询, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.数据库 = 父窗口.数据库 if 父窗口 else 数据库_mysql()
        self.网络 = 父窗口.网络 if 父窗口 else 网络连接()
        self.事件绑定()
        self.组件设置()

    def 组件设置(self):
        try:
            self.tableWidget_cqcx.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
            self.tableWidget_cqcx.horizontalHeader().setStyleSheet(
                "QHeaderView::section{background-color:rgb(40,143,218);font:9pt '宋体';color: white;};")
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            self.tableWidget_cqcx.dragEnterEvent = self.拖拽进来
            self.tableWidget_cqcx.dragMoveEvent = self.拖拽移动
            self.tableWidget_cqcx.dropEvent = self.拖拽放置
            self.pushButton_gxcbzl.clicked.connect(self.gxcbzl)
            self.pushButton_qk.clicked.connect(self.qingkong)
            self.pushButton_dc.clicked.connect(self.daochu)
            self.pushButton_cx.clicked.connect(self.chaxun)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def chaxun(self):
        try:
            pass
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def daochu(self):
        try:
            if self.tableWidget_cqcx.rowCount() == 0:
                self.statusbar.showMessage('没有数据', 2000)
            else:
                key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
                                     r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders')
                desktop = winreg.QueryValueEx(key, "Desktop")[0]
                self.表.to_excel(desktop + '/船期' + str(int(time.time())) + '.xlsx')
                self.statusbar.showMessage(desktop + '/船期' + str(int(time.time())) + '.xlsx-导出成功！', 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def qingkong(self):
        try:
            self.tableWidget_cqcx.setRowCount(0)
            self.statusbar.showMessage('清空成功！', 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def gxcbzl(self):
        try:
            self.网络.更新船舶资料数据库()
            self.statusbar.showMessage('更新成功！', 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 拖拽进来(self, event):  # 拖拽进来
        try:
            if event.mimeData().hasUrls:
                event.accept()
            else:
                event.ignore()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 拖拽移动(self, event):  # 拖拽移动
        try:
            if event.mimeData().hasUrls:
                event.accept()
            else:
                event.ignore()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 拖拽放置(self, event):  # 拖拽放置
        try:
            if event.mimeData().hasUrls:
                event.setDropAction(Qt.CopyAction)
                event.accept()
                文件名 = []
                for url in event.mimeData().urls():
                    文件名.append(str(url.toLocalFile()))
                self.文件名 = 文件名[0]
                self.statusbar.showMessage(self.文件名, 2000)

                中转 = self.表转换(self.文件名)
                self.表 = self.完善加填表(中转)
            else:
                event.ignore()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 表转换(self, 路径):
        try:
            if '.' in 路径:
                分割文本 = 路径.split(".")
                if 分割文本[-1] in 工具类.常量.船期查询_后缀范围:
                    try:
                        # 表格 = 工具类.获取pd表格(路径)
                        表格 = pd.read_excel(路径).fillna('空值')
                    except Exception as e:
                        工具类.logger.exception(e)
                        self.statusbar.showMessage('读取表格文件失败。')
                        return '-读取表格文件失败'
                    else:
                        表头 = 表格.columns.values.tolist()  # 获取表头
                        if '船名航次' in 表头:
                            结果 = pd.DataFrame(表格['船名航次'].value_counts())
                            结果.rename(columns={'船名航次': '数目'}, inplace=True)
                            结果['系统'] = ''
                            结果['船名代码'] = ''
                            结果['中文船名'] = ''
                            结果['出口航次'] = ''
                            结果['码头'] = ''
                            结果['预计到港时间'] = ''
                            结果['备注'] = ''
                            return 结果
                        else:
                            self.statusbar.showMessage('不是有效的表格文件', 2000)
                            return '-不是有效的表格文件'
                else:
                    self.statusbar.showMessage('文件格式不对，不是表格文件', 2000)
                    return '-文件格式不对，不是表格文件'
            else:
                self.statusbar.showMessage('不是文件路径', 2000)
                return '-不是文件路径'
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 船名转换(self, 船名):
        try:
            结果 = {'备注': ""}
            if '/' in 船名:
                船名子 = 船名.replace('(', '-')
                船名子 = 船名子.replace(')/', '-')
                船名子 = 船名子.split('-')
                结果['系统'] = 'HFQ'
                结果['船名代码'] = 船名子[0]
                结果['中文船名'] = 船名子[1]
                结果['出口航次'] = 船名子[2]
                返回 = self.数据库.查询数据('船舶资料', 字段列表=['船名代码'], 查询条件={'中文船名': 结果['中文船名']})
                返回数量 = len(返回)
                if 返回数量 == 0:
                    结果['备注'] = f"数据库无{结果['中文船名']}"
                else:
                    结果['船名代码'] = 返回[0][0]
                返回 = self.数据库.查询数据('zuijinchuanbojihua', 字段列表=['码头'],
                                   查询条件={'出口航次': 结果['出口航次'], '中文船名': 结果['中文船名']})
                返回数量 = len(返回)
                if 返回数量 == 0:
                    二次返回 = self.数据库.查询数据('zuijinchuanbojihua', 字段列表=['出口航次', '码头'],
                                         查询条件={'中文船名': 结果['中文船名']})
                    返回数量 = len(二次返回)
                    if 返回数量 == 0:
                        结果['备注'] = f"{结果['中文船名']}最近没有,码头暂定QQCT.11"
                        结果['码头'] = 'QQCT'
                    else:
                        显示内容 = '原船名:' + 船名 + ':\n'
                        for i in range(返回数量):
                            显示内容 = 显示内容 + str(i + 1) + ':' + 结果['船名代码'] + '/' + 结果['中文船名'] + '/' + \
                                   二次返回[i][0] + '\n'
                        输入内容, 选择状态 = QInputDialog.getText(self, '选择船名航次:', 显示内容)
                        if 选择状态 and 输入内容 != '':
                            索引 = int(输入内容) - 1
                            if int(输入内容) == 0:
                                结果['备注'] = '(%s)最近没有,用默认的,码头暂定QQCT.22' % 结果['中文船名']
                                结果['码头'] = 'QQCT'
                            else:
                                结果['出口航次'] = 二次返回[索引][0]
                                if 二次返回[索引][1] == '':
                                    结果['码头'] = 'QQCT'
                                elif len(二次返回[索引][1]) > 5:
                                    结果['码头'] = 二次返回[索引][1][:5]
                                else:
                                    结果['码头'] = 二次返回[索引][1]
                        else:
                            结果['备注'] = '(%s)最近没有,用默认的,码头暂定QQCT.33' % 结果['中文船名']
                            if 二次返回[0][1] == 0:
                                结果['码头'] = 'QQCT'
                            elif len(二次返回[0][1]) > 5:
                                结果['码头'] = 二次返回[0][1][:5]
                            else:
                                结果['码头'] = 二次返回[0][1]
                else:

                    if len(返回[0][0]) == 4:
                        结果['码头'] = 'QQCT'
                    elif len(返回[0][0]) >= 5:
                        结果['码头'] = 返回[0][0][:5]
                    else:
                        结果['码头'] = 返回[0][0]
                        结果['备注'] = '码头位数不对'
            else:
                结果['系统'] = 'GYJ'
                结果['船名代码'] = 船名[0:3]
                结果['出口航次'] = 船名[3:]
                返回 = self.数据库.查询数据('船舶资料', 字段列表=['中文船名'], 查询条件={'船名代码': 结果['船名代码']})
                返回数量 = len(返回)
                if 返回数量 == 0:
                    结果['中文船名'] = f"数据库无{结果['船名代码']}"
                    结果['备注'] = '数据库无(%s),码头暂定QQCT' % 结果['船名代码']
                    结果['码头'] = 'QQCT'
                else:
                    结果['中文船名'] = 返回[0][0]

                    返回 = self.数据库.查询数据('zuijinchuanbojihua', 字段列表=['码头'],
                                       查询条件={'船名代码': 结果['船名代码'], '出口航次': 结果['出口航次']})
                    if len(返回) == 0:
                        结果['备注'] = '(%s)最近没有,码头暂定QQCT' % 结果['中文船名']
                        结果['码头'] = 'QQCT'
                    else:
                        if len(返回[0][0]) == 4:
                            结果['码头'] = 返回[0]
                        elif len(返回[0][0]) >= 5:
                            结果['码头'] = 返回[0][0][:5]
                        else:
                            结果['码头'] = 返回[0][0]
                            结果['备注'] = '码头位数不对'
            return 结果
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 查询船期(self, 转换船名):

        try:
            a = self.网络.集装箱船舶计划(转换船名['船名代码'], 转换船名['中文船名'], 转换船名['出口航次'],
                                码头位置=转换船名['码头'])
            返回 = {}
            if a.get('结果', False):
                if a.get('数量', 0) == 0:
                    返回['结果'] = False
                    返回['错误描述'] = '集装箱船舶计划数量=0'
                elif a.get('数量', 1):
                    返回['结果'] = True
                    返回['数据'] = a.get('数据')[0]['预计到港时间']
                else:
                    返回['结果'] = False
                    返回['错误描述'] = '集装箱船舶计划数量大于1'
            else:
                返回['结果'] = False
                返回['错误描述'] = '集装箱船舶计划查询失败'
            return 返回

        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 完善加填表(self, 结果):
        try:
            列标签列表 = []
            删除行 = []
            for index, row in 结果.iterrows():
                if '新船' in index:
                    删除行.append(index)
                else:
                    列标签列表.append(index)
                信息 = self.船名转换(index)
                结果.loc[index, '系统'] = 信息['系统']
                结果.loc[index, '船名代码'] = 信息['船名代码']
                结果.loc[index, '中文船名'] = 信息['中文船名']
                结果.loc[index, '出口航次'] = 信息['出口航次']
                结果.loc[index, '码头'] = 信息['码头']
                结果.loc[index, '备注'] = 信息['备注']
                预计到港时间 = self.查询船期(信息)
                结果.loc[index, '预计到港时间'] = 预计到港时间.get('数据', "未知原因")

            结果.drop(index=删除行, inplace=True)
            原有 = self.tableWidget_cqcx.rowCount()
            self.tableWidget_cqcx.setRowCount(len(结果) + 原有)

            for i in range(len(结果)):
                单元格 = QTableWidgetItem(结果.loc[列标签列表[i], '系统'])
                单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                self.tableWidget_cqcx.setItem(i + 原有, 0, 单元格)

                单元格 = QTableWidgetItem(列标签列表[i])
                单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                self.tableWidget_cqcx.setItem(i + 原有, 1, 单元格)
                单元格 = QTableWidgetItem(结果.loc[列标签列表[i], '船名代码'])
                单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                self.tableWidget_cqcx.setItem(i + 原有, 2, 单元格)
                单元格 = QTableWidgetItem(结果.loc[列标签列表[i], '中文船名'])
                单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                self.tableWidget_cqcx.setItem(i + 原有, 3, 单元格)
                单元格 = QTableWidgetItem(结果.loc[列标签列表[i], '出口航次'])
                单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                self.tableWidget_cqcx.setItem(i + 原有, 4, 单元格)

                单元格 = QTableWidgetItem(结果.loc[列标签列表[i], '码头'])
                单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                self.tableWidget_cqcx.setItem(i + 原有, 5, 单元格)
                单元格 = QTableWidgetItem(str(结果.loc[列标签列表[i], '数目']))
                单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                self.tableWidget_cqcx.setItem(i + 原有, 6, 单元格)
                单元格 = QTableWidgetItem(结果.loc[列标签列表[i], '预计到港时间'])
                单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                self.tableWidget_cqcx.setItem(i + 原有, 7, 单元格)
                单元格 = QTableWidgetItem(结果.loc[列标签列表[i], '备注'])
                单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                self.tableWidget_cqcx.setItem(i + 原有, 8, 单元格)
            return 结果
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 计件统计(QMainWindow, 模块包.计件统计.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super(计件统计, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.事件绑定()
        self.组件设置()
        self.表格 = None  # 初始化表格变量

    def 组件设置(self):
        try:
            self.riqigaibian()
            self.tableWidget_paiban.horizontalHeader().setStyleSheet(
                "QHeaderView::section{background-color:rgb(40,143,218);font:9pt '宋体';color: white;};")

            self.tableWidget_jjtj.resizeColumnsToContents()
            self.tableWidget_jjtj.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
            self.tableWidget_jjtj.horizontalHeader().setStyleSheet(
                "QHeaderView::section{background-color:rgb(40,143,218);font:9pt '宋体';color: white;};")
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            self.dateEdit.dateChanged.connect(self.riqigaibian)
            self.pushButton_qingkong.clicked.connect(self.qingkong)
            self.pushButton_huifu.clicked.connect(self.riqigaibian)
            self.pushButton_jisuan.clicked.connect(self.jisuan)

            self.tableWidget_jjtj.dragEnterEvent = self.拖拽进来
            self.tableWidget_jjtj.dragMoveEvent = self.拖拽移动
            self.tableWidget_jjtj.dropEvent = self.拖拽放置
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def qingkong(self):
        try:
            self.tableWidget_jjtj.setRowCount(0)
            self.statusbar.showMessage('')
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 拖拽进来(self, event):  # 拖拽进来
        try:
            if event.mimeData().hasUrls:
                event.accept()
            else:
                event.ignore()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 拖拽移动(self, event):  # 拖拽移动
        try:
            if event.mimeData().hasUrls:
                event.accept()
            else:
                event.ignore()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 拖拽放置(self, event):  # 拖拽放置
        try:
            if event.mimeData().hasUrls:
                event.setDropAction(Qt.CopyAction)
                event.accept()
                urls = event.mimeData().urls()
                if urls:
                    self.表格 = self.导入(urls[0].toLocalFile())
                    self.jisuan()

            else:
                event.ignore()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def riqigaibian(self):
        try:
            date = self.dateEdit.date()
            年 = date.year()
            月 = date.month()
            天数 = calendar.monthrange(年, 月)[1]
            self.tableWidget_paiban.setRowCount(天数)
            for i in range(天数):
                操作人 = 工具类.日期到操作人(f'{年}-{月}-{i + 1}')
                白班 = QTableWidgetItem(操作人['白班'])
                白班.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                self.tableWidget_paiban.setItem(i, 0, 白班)
                夜班 = QTableWidgetItem(操作人['夜班'])
                夜班.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                self.tableWidget_paiban.setItem(i, 1, 夜班)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 时间通过表格到操作人(self, 文本时间):
        try:
            if 文本时间 == '空值':
                return '空值'

            给定时间 = parse(str(文本时间))
            上班日期 = 给定时间.day
            上班时间 = 给定时间.time()
            班次 = 0 if parse('08:30:00').time() <= 上班时间 < parse('17:30:00').time() else 1

            if parse('00:00:00').time() <= 上班时间 < parse('08:30:00').time():
                上班日期 -= 1
            if 上班日期 - 1 >= 0:
                return self.tableWidget_paiban.item(上班日期 - 1, 班次).text()
            else:
                前一天时间 = 给定时间 - timedelta(days=1)
                前一天日期 = str(前一天时间.today())
                return 工具类.日期到操作人(前一天日期)['夜班']
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def ceshi(self):
        try:
            时间 = '2024-08-03 02:00:00'
            操作人 = self.时间通过表格到操作人(时间)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def jisuan(self):
        try:
            self.qingkong()
            if self.表格 is not None:
                self.统计(self.表格)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 导入(self, 路径):
        try:
            if '.' in 路径 and 路径.split(".")[-1] in 工具类.常量.计件统计_后缀范围:
                try:
                    表格 = pd.read_excel(路径).fillna('空值')
                    表格['操作人'] = ''
                    return 表格
                except Exception as e:
                    工具类.logger.exception(e)
                    self.statusbar.showMessage('读取表格文件失败', 2000)
            else:
                self.statusbar.showMessage(f'{路径} 不是有效的表格文件', 2000)
            return None
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 统计(self, 表格):
        try:
            表头 = self.表格.columns.values.tolist()  # 获取表头
            行数 = self.表格.shape[0]

            if '进出场时间' in 表头 and '出场人' in 表头 and '箱号' in 表头:
                for i in range(行数):
                    if 表格.loc[i]['出场人'] in ['AUTOGATE', 'AutoGate']:
                        操作人 = self.时间通过表格到操作人(表格.loc[i]['进出场时间'])
                        表格.loc[i, '操作人'] = 操作人.strip()
                    else:
                        表格.loc[i, '操作人'] = 表格.loc[i]['出场人'].strip()
                self.tableWidget_jjtj.setRowCount(行数)
                for i in range(行数):
                    单元格 = QTableWidgetItem(表格['箱号'][i])
                    单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                    self.tableWidget_jjtj.setItem(i, 0, 单元格)
                    单元格 = QTableWidgetItem(表格['进出场时间'][i])
                    单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                    self.tableWidget_jjtj.setItem(i, 1, 单元格)
                    单元格 = QTableWidgetItem(表格['出场人'][i])
                    单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                    self.tableWidget_jjtj.setItem(i, 2, 单元格)
                    单元格 = QTableWidgetItem(表格['操作人'][i])
                    单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                    self.tableWidget_jjtj.setItem(i, 3, 单元格)
                self.statusbar.showMessage('操作成功')
                结果 = 表格['操作人'].value_counts()
                内容 = ' | '.join([f'{i}:{结果[i]}' for i in 结果.index])
                self.statusbar.showMessage(内容)
            else:
                self.statusbar.showMessage('表格文件缺少必要字段')
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 综合查询(QMainWindow, 模块包.综合查询.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super(综合查询, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.数据库 = 父窗口.数据库 if 父窗口 else 数据库_mysql()
        self.网络 = 父窗口.网络 if 父窗口 else 网络连接()
        self.组件设计()
        self.事件绑定()

    def 组件设计(self):
        try:
            # 建立正则语句并绑定正则验证器
            正则语句 = QRegExp('[a-zA-Z0-9]+$')  # 建立正则语句
            正则验证器 = QRegExpValidator(正则语句, self)  # 实例化正则验证器
            self.lineEdit_xh.setValidator(正则验证器)  # 绑定正则验证器

            # 设置样式表
            self.lineEdit_xh.setStyleSheet("background:" + self.数据库.获取属性值('综合查询箱号背景色', "yellow"))
            self.comboBox_mhcz.setStyleSheet(
                "background:" + self.数据库.获取属性值('综合查询船名航次背景色', "yellow"))
            self.lineEdit_cz.setStyleSheet(
                "background:" + self.数据库.获取属性值('综合查询合作场站背景色', "yellow"))
            self.setStyleSheet('background-color:rgb(170, 255, 255)')

            # 设置表格样式
            self.tableWidget_edi.horizontalHeader().setStyleSheet(
                "QHeaderView::section{background-color:" + self.数据库.获取属性值('综合查询EDI表头背景色',
                                                                          "yellow") + ";font:8pt '微软雅黑';color: " + self.数据库.获取属性值(

                    '综合查询EDI表头字体色', "#000000") + ";};")
            self.tableWidget_cbjh.horizontalHeader().setStyleSheet(
                "QHeaderView::section{background-color:" + self.数据库.获取属性值('综合查询CBJH表头背景色',
                                                                          "yellow") + ";font:8pt '微软雅黑';color: " + self.数据库.获取属性值(
                    '综合查询CBJH表头字体色', "#000000") + ";};")

            self.tableWidget_sxjh.horizontalHeader().setStyleSheet(
                "QHeaderView::section{background-color:" + self.数据库.获取属性值('综合查询SXJH表头背景色',
                                                                          "yellow") + ";font:" + self.数据库.获取属性值(

                    '综合查询SXJH表头字体大小',
                    "8") + "pt '微软雅黑';color: " + self.数据库.获取属性值('综合查询SXJH表头字体色', "#000000") + ";};")

            # self.tableWidget_sxjh.setStyleSheet("font: 9pt \"隶书\";")
            # self.setWindowIcon(QIcon('test.ico'))  # 设置图标
            # 设置表格大小调整模式
            self.tableWidget_edi.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
            self.tableWidget_cbjh.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
            self.tableWidget_sxjh.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)

            # 设置关注场站和最近船名航次列表
            self.置关注场站(self.父窗口.场站组)
            self.置最近船名航次列表(self.父窗口.船名组)

            # 设置表格初始高度
            self.tableWidget_edi.setMinimumHeight(工具类.常量.综合查询_信息表格初始高度)
            self.tableWidget_edi.setMaximumHeight(工具类.常量.综合查询_信息表格初始高度)
            self.tableWidget_cbjh.setMinimumHeight(工具类.常量.综合查询_船舶计划表格初始高度)
            self.tableWidget_cbjh.setMaximumHeight(工具类.常量.综合查询_船舶计划表格初始高度)

            # 设置表格大小调整模式
            # self.tableWidget_edi.resizeColumnsToContents()
            # self.tableWidget_cbjh.resizeColumnsToContents()
            # self.tableWidget_sxjh.resizeColumnsToContents()

            self.tableWidget_edi.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
            self.tableWidget_cbjh.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
            self.tableWidget_sxjh.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)

            # 设置下拉框
            self.comboBox_mhcz.setFocusPolicy(Qt.StrongFocus)
            self.comboBox_mhcz.setEditable(True)

            self.comboBox_mhcz.pFilterModel = QSortFilterProxyModel(self.comboBox_mhcz)
            self.comboBox_mhcz.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)  # 大小不敏感
            self.comboBox_mhcz.pFilterModel.setSourceModel(self.comboBox_mhcz.model())

            self.comboBox_mhcz.completer = QCompleter(self.comboBox_mhcz.pFilterModel, self.comboBox_mhcz)
            self.comboBox_mhcz.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
            # self.comboBox_mhcz.completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)  # 不区分大小写
            self.comboBox_mhcz.setCompleter(self.comboBox_mhcz.completer)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            self.comboBox_mhcz.lineEdit().textEdited.connect(self.comboBox_mhcz.pFilterModel.setFilterFixedString)
            self.comboBox_mhcz.activated.connect(self.xllbxzxx)  # 下拉列表选中选项
            # self.comboBox_mhcz.completer.activated.connect(self.on_completer_activated)
            self.pushButton_shuaxin.clicked.connect(self.shuaxin)  # 刷新按钮
            self.lineEdit_xh.textEdited.connect(self.bjknrgb)  # 编辑框内容改变
            self.tableWidget_cbjh.cellDoubleClicked.connect(self.chuanbojihuashuangji)  # 双击表格中的单元格，发出信号，并传递(行，列)
            self.tableWidget_edi.cellDoubleClicked.connect(self.zhuangxiangdanshuangji)  # 双击表格中的单元格，发出信号，并传递(行，列)
            self.lineEdit_xh.focusInEvent = self.huoqujiaodian1
            self.comboBox_mhcz.focusInEvent = self.huoqujiaodian2
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 置最近船名航次列表(self, 船名组):
        try:
            self.comboBox_mhcz.clear()
            self.comboBox_mhcz.addItems([""] + 船名组)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 置关注场站(self, 场站组):
        try:
            self.lineEdit_cz.setText('不限；' + '；'.join(场站组))
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def huoqujiaodian1(self, 事件):
        try:
            self.comboBox_mhcz.setEditText('')
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def huoqujiaodian2(self, 事件):
        try:
            self.lineEdit_xh.setText('')
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def shuaxin(self):  # 刷新按钮
        try:
            self.清空表格()
            工具类.播放音乐(r'音效/点击.mp3')
            编辑框内容 = self.lineEdit_xh.text()
            下拉框内容 = self.comboBox_mhcz.currentText()
            if 编辑框内容 == "" and 下拉框内容 != "":
                self.statusbar.showMessage('刷新:%s' % 下拉框内容, 2000)
                self.xllbxzxx()
            elif 编辑框内容 != "" and 下拉框内容 == "":
                self.statusbar.showMessage('刷新:%s' % 编辑框内容, 2000)
                self.bjknrgb(编辑框内容)
            elif 编辑框内容 != "" and 下拉框内容 != "":
                self.statusbar.showMessage('两个都不是空的，刷新那一个？', 2000)
            else:
                self.statusbar.showMessage('两个都是空的，刷新什么！', 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def zhuangxiangdanshuangji(self, 行号, 列号):  # 双击装箱单表格
        try:
            船名代码 = self.tableWidget_edi.item(行号, 2).text()[:3]
            中文船名 = self.tableWidget_edi.item(行号, 1).text()
            出口航次 = self.tableWidget_edi.item(行号, 2).text()[3:]
            登录返回信息 = self.网络.登录返回信息()
            if 登录返回信息.get('结果', False):
                self.集装箱船舶计划查询填表(船名代码, 中文船名, 出口航次)
            else:
                self.statusbar.showMessage('没有登录', 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def chuanbojihuashuangji(self, 行号, 列号):  # 双击船舶计划表格
        try:
            码头位置 = ''.join(re.findall(r'[A-Za-z]', self.tableWidget_cbjh.item(行号, 0).text()))
            中文船名 = self.tableWidget_cbjh.item(行号, 工具类.常量.综合查询_船舶计划表格中文船名列号).text()
            英文船名 = self.tableWidget_cbjh.item(行号, 工具类.常量.综合查询_船舶计划表格英文船名列号).text()
            出口航次 = self.tableWidget_cbjh.item(行号, 工具类.常量.综合查询_船舶计划表格船名航次列号).text()[3:]
            船名代码 = self.tableWidget_cbjh.item(行号, 工具类.常量.综合查询_船舶计划表格船名航次列号).text()[:3]
            登录返回信息 = self.网络.登录返回信息()
            if 登录返回信息.get('结果', False):
                self.收箱计划查询填表(码头位置, 中文船名, 英文船名, 出口航次, 船名代码)
            else:
                self.statusbar.showMessage('没有登录', 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def bjknrgb(self, 编辑框内容):  # 编辑框内容改变
        try:
            self.清空表格()
            self.lineEdit_xh.setText(编辑框内容.upper())
            if 编辑框内容 == '':
                self.statusbar.showMessage('编辑框内容为空', 2000)
            elif len(编辑框内容) == 11:
                工具类.播放音乐(r'音效/点击.mp3')
                if self.父窗口.登陆状态:
                    self.statusbar.showMessage('装箱单查询:' + 编辑框内容, 2000)
                    self.装箱单查询填表(编辑框内容)
                else:
                    self.statusbar.showMessage('没有登录', 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 清空表格(self):
        try:
            self.tableWidget_edi.setRowCount(0)
            self.tableWidget_cbjh.setRowCount(0)
            self.tableWidget_sxjh.setRowCount(0)
            self.tableWidget_edi.setMinimumHeight(工具类.常量.综合查询_信息表格初始高度)
            self.tableWidget_edi.setMaximumHeight(工具类.常量.综合查询_信息表格初始高度)
            self.tableWidget_cbjh.setMinimumHeight(工具类.常量.综合查询_船舶计划表格初始高度)
            self.tableWidget_cbjh.setMaximumHeight(工具类.常量.综合查询_船舶计划表格初始高度)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def xllbxzxx(self):  # 下拉列表选中选项
        try:
            self.清空表格()
            内容 = self.comboBox_mhcz.currentText()
            a = 内容.find('/', 0, len(内容))
            b = 内容.rfind('/', 0, len(内容))
            船名代码 = 内容[:a]
            中文船名 = 内容[a + 1:b]
            出口航次 = 内容[b + 1:]

            self.tableWidget_edi.setRowCount(0)
            self.tableWidget_edi.setMinimumHeight(工具类.常量.综合查询_信息表格初始高度)
            self.tableWidget_edi.setMaximumHeight(工具类.常量.综合查询_信息表格初始高度)
            工具类.播放音乐(r'音效/点击.mp3')
            if self.父窗口.登陆状态:
                self.statusbar.showMessage('集装箱船舶计划:' + 内容, 2000)
                self.集装箱船舶计划查询填表(船名代码, 中文船名, 出口航次)
            else:
                self.statusbar.showMessage('没有登录', 2000)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 装箱单查询填表(self, 箱号):
        try:

            装箱单列表 = self.网络.装箱单(箱号)
            if 装箱单列表.get('结果', False):
                self.装箱单填表(装箱单列表['数据'])
            else:
                self.清空表格()
            self.tableWidget_edi.resizeColumnsToContents()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 装箱单填表(self, 数据):
        try:
            行数 = len(数据)
            if 行数 == 0:
                self.清空表格()
            else:
                self.tableWidget_edi.setRowCount(行数)
                self.tableWidget_edi.setMinimumHeight((行数 + 2) * self.tableWidget_edi.rowHeight(0))
                self.tableWidget_edi.setMaximumHeight((行数 + 2) * self.tableWidget_edi.rowHeight(0))
                是否查询 = True
                for 索引, 值 in enumerate(数据):
                    天数 = (datetime.now() - datetime.strptime(值.get('接受时间', ''), '%Y-%m-%d %H:%M')).days
                    颜色 = 工具类.常量.综合查询_信息最近绿 if 天数 < 2 else 工具类.常量.综合查询_信息过期灰
                    列数据 = [
                        ''.join(re.findall(r'[A-Za-z]', 值['码头'])),
                        值['中文船名'],
                        值['船名代码'] + 值['航次'],
                        值['箱站代码'],
                        值['内外贸'],
                        值['卸货港'],
                        值['分单号'],
                        值['英文船名'],
                        值['箱皮重'],
                        值['毛重'],
                        值['提前申报标志'],
                        值['接受时间'],
                        值['回执状态'],
                        值['回执描述'],
                        ''
                    ]
                    for 列号, 内容 in enumerate(列数据):
                        单元格 = QTableWidgetItem(内容)
                        单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                        单元格.setBackground(颜色)
                        self.tableWidget_edi.setItem(索引, 列号, 单元格)
                    if 是否查询 and 天数 < 2:
                        船名代码 = 值.get('船名代码', '')
                        中文船名 = 值.get('中文船名', '')
                        出口航次 = 值.get('航次', '')
                        self.集装箱船舶计划查询填表(船名代码, 中文船名, 出口航次)
                        是否查询 = False
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 集装箱船舶计划查询填表(self, 船名代码, 中文船名, 出口航次):
        try:
            集装箱船舶计划列表 = self.网络.集装箱船舶计划(船名代码, 中文船名, 出口航次)

            if 集装箱船舶计划列表.get('结果', False):
                self.集装箱船舶计划填表(集装箱船舶计划列表.get('数据', []))
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 集装箱船舶计划填表(self, 数据):
        try:
            行数 = len(数据)
            if 行数 == 0:
                self.tableWidget_cbjh.setRowCount(0)
                self.tableWidget_cbjh.setMinimumHeight(工具类.常量.综合查询_船舶计划表格初始高度)
                self.tableWidget_cbjh.setMaximumHeight(工具类.常量.综合查询_船舶计划表格初始高度)
                self.tableWidget_sxjh.setRowCount(0)
            else:
                列数据 = [
                    ''.join(re.findall(r'[A-Za-z]', 数据[0]['码头'])),
                    数据[0]['中文船名'],
                    数据[0]['船名代码'] + 数据[0]['出口航次'],
                    数据[0]['泊位'],
                    数据[0]['内外贸'],
                    数据[0]['英文船名'],
                    数据[0]['预计到港时间'],
                    数据[0]['收箱结束时间'],
                    '']
                self.tableWidget_cbjh.setRowCount(1)
                for 列号, 内容 in enumerate(列数据):
                    单元格 = QTableWidgetItem(内容)
                    单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                    单元格.setBackground(工具类.常量.综合查询_船舶计划绿)
                    self.tableWidget_cbjh.setItem(0, 列号, 单元格)
                self.tableWidget_cbjh.resizeColumnsToContents()
                self.收箱计划查询填表(
                    码头位置=''.join(re.findall(r'[A-Za-z]', 数据[0]['码头'])),
                    中文船名=数据[0]['中文船名'],
                    英文船名=数据[0]['英文船名'],
                    出口航次=数据[0]['出口航次'],
                    船名代码=数据[0]['船名代码'])
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 收箱计划查询填表(self, 码头位置, 中文船名, 英文船名, 出口航次, 船名代码):
        try:
            self.tableWidget_sxjh.setRowCount(0)
            收箱截货计划列表 = self.网络.收箱截货计划(码头位置, 中文船名, 英文船名, 出口航次, 船名代码)

            if 收箱截货计划列表.get('结果', False):
                self.收箱计划填表(收箱截货计划列表['数据'])

        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 收箱计划填表(self, 数据):
        try:
            行数 = len(数据)
            if 行数 == 0:
                self.tableWidget_sxjh.setRowCount(0)
            else:
                self.tableWidget_sxjh.setRowCount(行数)
                for 索引, 值 in enumerate(数据):
                    开始时间 = datetime.strptime(值.get('收箱开始时间'), '%Y-%m-%d %H:%M:%S')
                    结束时间 = datetime.strptime(值.get('收箱结束时间'), '%Y-%m-%d %H:%M:%S')
                    现在时间 = datetime.now()

                    if 值['箱站代码'] in self.lineEdit_cz.text():
                        颜色 = 工具类.常量.综合查询_未来蓝 if 现在时间 < 开始时间 else (工具类.常量.综合查询_无关灰 if 结束时间 < 现在时间 else 工具类.常量.综合查询_进行绿)

                    else:
                        颜色 = 工具类.常量.综合查询_无关灰

                    列数据 = [
                        值['码头'],
                        值['中文船名'],
                        值['船名代码'] + 值['出口航次'],
                        值['箱站代码'],
                        值['空重'],
                        值['收箱开始时间'],
                        值['收箱结束时间'],
                        值['加急标志'],
                        值['加急截止时间'],
                        值['备注'],
                        ''
                    ]

                    for 列号, 内容 in enumerate(列数据):
                        单元格 = QTableWidgetItem(内容)
                        单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                        单元格.setBackground(颜色)
                        self.tableWidget_sxjh.setItem(索引, 列号, 单元格)

                self.tableWidget_sxjh.resizeColumnsToContents()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 主体程序(QMainWindow, 模块包.主窗口.Ui_MainWindow):

    def __init__(self, 父窗口=None, 数据库=None, 全局控制=None, 网络=None):
        开始时间 = time.time()
        try:
            super(主体程序, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.全局控制 = 全局控制
        self.登陆状态 = False
        self.网络 = 网络 if 网络 else 网络连接()
        self.数据库 = 数据库 if 数据库 else 数据库_mysql()
        self.心跳定时器 = QTimer()
        self.状态栏定时器 = QTimer()
        self.当前用户 = '游客'
        self.权限组件 = {'用户维护': self.action_yhgl,
                     '运港通登录': self.action_ygtdl,
                     '运港通快捷登录': self.action_ygtkjdl,
                     '综合查询': self.action_zhcx,
                     '多样查询': self.action_dycx,
                     '船期查询': self.action_cqcx,
                     '最近船期': self.action_zuijcq,
                     '集港时间': self.action_jgss,
                     '外点返场': self.action_wdfc,
                     '集港出场': self.action_jgcc,
                     '出口下货纸': self.action_ckxhz,
                     '补工作证': self.action_bgzz,
                     '表格改造': self.action_bggz,
                     '计件统计': self.action_jjtj,
                     '场站维护': self.action_czwh,
                     '尺寸维护': self.action_ccwh,
                     '箱型维护': self.action_xxwh,
                     '箱属维护': self.action_xswh,
                     '客户维护': self.action_khwh,
                     '航次维护': self.action_hcwh,
                     '费目维护': self.action_fmwh,
                     '车队维护': self.action_cdwh,
                     '船名代码维护': self.action_cmdmwh,
                     '动态类型维护': self.action_dtlxwh,
                     '动态大类维护': self.action_dtdlwh,
                     '拖车类型维护': self.action_tclxwh,
                     '超级管理员维护': self.action_cjglywh,
                     '笔趣阁': self.action_bqg,
                     '酷狗音乐': self.action_kgyy,
                     '属性设置': self.action_sxsz,
                     '权限设置': self.action_qxsz,
                     '显示日志框': self.action_rzk}
        self.绑定方法 = {'用户维护': self.add_yonghuguanli,
                     '运港通登录': self.add_yungangtongdenglu,
                     '运港通快捷登录': self.yungangtongkuaijiedenglu,
                     '综合查询': self.add_zonghechaxun,
                     '多样查询': self.add_duoyangchaxun,
                     '船期查询': self.add_chuanqichaxun,
                     '最近船期': self.add_zuijinchuanqi,
                     '集港时间': self.add_jigangshijian,
                     '外点返场': self.add_waidianfanchang,
                     '集港出场': self.add_jigangchuchang,
                     '出口下货纸': self.add_chukouxiahuozhi,
                     '补工作证': self.add_bugongzuozheng,
                     '表格改造': self.add_biaogegaizao,
                     '计件统计': self.add_jijiantongji,
                     '场站维护': self.add_changzhanweihu,
                     '尺寸维护': self.add_chicunweihu,
                     '箱型维护': self.add_xiangxingweihu,
                     '箱属维护': self.add_xiangshuweihu,
                     '客户维护': self.add_kehuweihu,
                     '航次维护': self.add_hangciweihu,
                     '费目维护': self.add_feimuweihu,
                     '车队维护': self.add_cheduiweihu,
                     '船名代码维护': self.add_chuanmingweihu,
                     '动态类型维护': self.add_dongtaileixingweihu,
                     '动态大类维护': self.add_dongtaidaleiweihu,
                     '拖车类型维护': self.add_tuocheleixingweihu,
                     '超级管理员维护': self.add_cjglywh,
                     '笔趣阁': self.add_biquge,
                     '酷狗音乐': self.add_kugouyinyue,
                     '属性设置': self.add_shuxingshezhi,
                     '权限设置': self.add_quanxianshezhi,
                     '显示日志框': self.rizhikuang}
        # self.检查运行环境()
        self.属性配置()
        self.事件绑定()
        self.状态栏定时器.start(1000)
        self.托盘程序 = 托盘(self)
        self.组件设计()
        self.show()
        结束时间 = time.time()
        工具类.logger.info(f'打开软件花费{结束时间 - 开始时间}秒时间!')
        self.textEdit_gzrz.append(f'打开软件花费{结束时间 - 开始时间}秒时间!')

    def 检查运行环境(self):
        try:
            self.数据库初始化()
            self.检查依赖(工具类.常量.依赖环境)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 属性配置(self):
        try:
            self.启动音效 = self.数据库.获取属性值('启动音效', '音效/启动.mp3')
            self.登录音效 = self.数据库.获取属性值('登录音效', '音效/登录.mp3')
            self.点击音效 = self.数据库.获取属性值('点击音效', '音效/点击.mp3')
            self.断开音效 = self.数据库.获取属性值('断开音效', '音效/断开.mp3')
            self.心跳时间 = int(self.数据库.获取属性值('心跳时间', '300000'))

            标记箱站 = self.数据库.查询数据('changzhan', 字段列表=['场站代码'], 查询条件={'标记状态': '标记'})
            self.场站组 = [i[0] for i in 标记箱站]
            self.船名组 = []

            self.心跳定时器.start(self.心跳时间)
            self.心跳定时器.stop()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 检查依赖(self, 依赖环境):
        try:
            运行目录 = os.path.dirname(os.path.abspath(__file__))
            现有环境 = []
            for i, j, k in os.walk(运行目录):
                现有环境 += k
            for i in 依赖环境:
                if i not in 现有环境:
                    self.textEdit_gzrz.append(f'缺少{i}依赖环境!')
                    工具类.logger.error(f'缺少{i}依赖环境!')
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 数据库初始化(self):
        try:
            属性键值对 = {'出口航次': 'TEXT', '英文船名': 'TEXT', '船名代码': 'TEXT', '码头': 'TEXT',
                     '预计到港时间': 'TEXT', '中文船名': 'TEXT', '描述': 'TEXT'}
            self.数据库.创建数据库表('zuijinchuanbojihua', 属性键值对)

            属性键值对 = {'中文船名': 'TEXT', '英文船名': 'TEXT', '船名代码': 'TEXT', '船公司码': 'TEXT',
                     '描述': 'TEXT'}
            self.数据库.创建数据库表('chuanboziliao', 属性键值对)

            属性键值对 = {'属性': 'TEXT', '值': 'TEXT', '描述': 'TEXT'}
            if self.数据库.创建数据库表('zhuti', 属性键值对):
                zh = "{'心跳时间':'20000','启动音效':'音效/启动.mp3','点击音效':'音效/点击.mp3','断开音效':'音效/断开.mp3','登录音效':'音效/登录.mp3','综合查询箱号背景色':'#ffff7f','综合查询船名航次背景色':'#ffff7f','综合查询合作场站背景色':'#aaaa7f','综合查询EDI表头背景色':'#55aaff','综合查询CBJH表头背景色':'#55aaff','综合查询SXJH表头背景色':'#55aaff','综合查询EDI表头字体色':'#000000','综合查询CBJH表头字体色':'#000000','综合查询SXJH表头字体色':'#000000'}"
                self.数据库.插入多条数据('主题', [('属性', zh)])

            属性键值对 = {'场站代码': 'TEXT', '场站名称': 'TEXT', '标记状态': 'TEXT', '描述': 'TEXT'}
            self.数据库.创建数据库表('changzhan', 属性键值对)

            属性键值对 = {'尺寸大小': 'TEXT', '尺寸代码': 'TEXT', '标记状态': 'TEXT', '描述': 'TEXT'}
            self.数据库.创建数据库表('chicun', 属性键值对)

            属性键值对 = {'箱型代码': 'TEXT', '箱型名称': 'TEXT', '标记状态': 'TEXT', '描述': 'TEXT'}
            self.数据库.创建数据库表('xiangxing', 属性键值对)
            属性键值对 = {'箱属代码': 'TEXT', '箱属名称': 'TEXT', '标记状态': 'TEXT', '描述': 'TEXT'}
            self.数据库.创建数据库表('xiangshu', 属性键值对)

            属性键值对 = {'客户代码': 'TEXT', '客户名称': 'TEXT', '标记状态': 'TEXT', '描述': 'TEXT'}
            self.数据库.创建数据库表('kehu', 属性键值对)

            属性键值对 = {'航次代码': 'TEXT', '航次名称': 'TEXT', '标记状态': 'TEXT', '描述': 'TEXT'}
            self.数据库.创建数据库表('hangci', 属性键值对)

            属性键值对 = {'费目代码': 'TEXT', '费目名称': 'TEXT', '标记状态': 'TEXT', '描述': 'TEXT'}
            self.数据库.创建数据库表('feimu', 属性键值对)
            属性键值对 = {'车队代码': 'TEXT', '车队名称': 'TEXT', '标记状态': 'TEXT', '描述': 'TEXT'}
            self.数据库.创建数据库表('chedui', 属性键值对)

            属性键值对 = {'动态类型代码': 'TEXT', '动态类型名称': 'TEXT', '标记状态': 'TEXT', '描述': 'TEXT'}
            self.数据库.创建数据库表('dongtaileixing', 属性键值对)

            属性键值对 = {'动态大类代码': 'TEXT', '动态大类名称': 'TEXT', '标记状态': 'TEXT', '描述': 'TEXT'}
            self.数据库.创建数据库表('dongtaidalei', 属性键值对)

            属性键值对 = {'拖车类型代码': 'TEXT', '拖车类型名称': 'TEXT', '标记状态': 'TEXT', '描述': 'TEXT'}
            self.数据库.创建数据库表('tuocheleixing', 属性键值对)

            属性键值对 = {'用户名': 'TEXT', '账号': 'TEXT', '密码': 'TEXT', '标记状态': 'TEXT', '描述': 'TEXT'}
            self.数据库.创建数据库表('yonghu', 属性键值对)

            工具类.logger.info('数据库初始化完毕')
            self.textEdit_gzrz.append('数据库初始化完毕')
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 组件设计(self):
        try:
            权限 = eval(工具类.常量.游客权限)
            for key, value in 权限.items():
                self.权限组件[key].setEnabled(value)
            self.setWindowTitle('雨晨科技公司欢迎你！   ' + '当前是：游客')
            self.add_zonghechaxun(是否有音效=False)  # 综合查询
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            # 定时器.timeout信号与事件绑定
            self.心跳定时器.timeout.connect(self.xintiao)
            self.状态栏定时器.timeout.connect(self.zhuangtailan)

            self.tabWidget.tabCloseRequested.connect(self.close_tab)  # 页面X绑定关闭
            self.tabWidget.tabBarDoubleClicked.connect(self.close_tab)  # 双击标签X绑定关闭

            for key, value in self.权限组件.items():
                value.triggered.connect(self.绑定方法[key])
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 置权限(self, 当前用户):
        try:
            if 当前用户 == '游客':
                权限 = eval(工具类.常量.游客权限)
                for key, value in 权限.items():
                    self.权限组件[key].setEnabled(value)
            else:
                权限文本 = self.数据库.查询数据('yonghu', 字段列表=['权限'], 查询条件={'用户名': 当前用户})
                权限 = eval(权限文本[0][0])
                for key, value in 权限.items():
                    self.权限组件[key].setEnabled(value)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 登录后操作(self):
        try:
            登录返回值 = self.网络.登录返回信息()
            if not 登录返回值.get('结果', False):
                self.statusbar.showMessage(登录返回值.get('原文', '未知原因'))
            else:
                工具类.播放音乐(self.登录音效)
                self.登陆状态 = True
                self.当前用户 = 登录返回值.get('用户名', '游客')
                self.setWindowTitle(
                    f"雨晨科技公司欢迎你！   {self.当前用户}({登录返回值.get('用户公司', '*')}),登录时间：{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
                self.置权限(self.当前用户)
                self.登陆状态 = True
                退出提示框 = QMessageBox.question(self, "提示", f"是否要更新最近船舶计划？", QMessageBox.Yes | QMessageBox.No,
                                             QMessageBox.No)
                if 退出提示框 == QMessageBox.Yes:
                    self.更新最近船舶计划()

                if self.综合查询:
                    船名 = self.数据库.查询数据('zuijinchuanbojihua', 字段列表=['船名代码', '中文船名', '出口航次'])
                    self.船名组 = [i[0] + '/' + i[1] + '/' + i[2] for i in 船名]
                    self.综合查询.置最近船名航次列表(self.船名组)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 获取标记账号密码(self):
        try:
            数据 = self.数据库.查询数据('yonghu', 字段列表=['账号', '密码'], 查询条件={'标记状态': '标记'})
            if not 数据:
                工具类.logger.info('《yonghu》没有标记状态为标记的账号')
                return '', ''
            return 数据[0][0], 数据[0][1]
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 更新最近船舶计划(self):
        try:
            数据 = self.网络.最近船舶计划('')
            字段列表 = self.数据库.获取所有字段名('zuijinchuanbojihua')
            if 'id' in 字段列表:
                字段列表.remove('id')
            多行数据 = [[i.get(j, '**') for j in 字段列表] for i in 数据['数据']]
            self.数据库.插入多条数据('zuijinchuanbojihua', 多行数据)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def closeEvent(self, a0: QtGui.QCloseEvent):
        try:
            # self.托盘程序.运行()
            self.tuichu()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def xintiao(self):
        try:
            信息 = self.网络.登录返回信息()
            if 信息.get('结果', False):
                self.登陆状态 = True
                工具类.logger.debug('心跳-在线')
                self.textEdit_gzrz.append('心跳-在线')
            else:
                if self.登陆状态:
                    工具类.播放音乐(self.断开音效)
                    退出提示框 = QMessageBox.question(self, "提示", "检测到系统已退出，是否快捷登录？",
                                                 QMessageBox.Yes | QMessageBox.No,
                                                 QMessageBox.No)
                    if 退出提示框 == QMessageBox.Yes:
                        self.yungangtongkuaijiedenglu()
                        工具类.logger.debug('心跳-重新登录')
                        self.textEdit_gzrz.append('心跳-重新登录')
                    else:
                        工具类.logger.debug('心跳-掉线')
                        self.textEdit_gzrz.append('心跳-掉线')
                        self.登陆状态 = False
                        self.setWindowTitle('雨晨科技公司欢迎你！   ' + '当前是：游客模式')
                else:
                    工具类.logger.debug('心跳-离线')
                    self.textEdit_gzrz.append('心跳-离线')
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def zhuangtailan(self):
        try:
            时间 = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            self.statusbar.showMessage(f'状态：{self.登陆状态}  |  网络时间：{时间}')
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def yungangtongkuaijiedenglu(self):
        try:
            账号, 密码 = self.获取标记账号密码()
            if not 账号:
                return
            返回信息 = self.网络.快速登录(账号, 密码)
            if 返回信息.get('结果', False):
                工具类.播放音乐(self.登录音效)
                self.当前用户 = 返回信息.get('用户名', '游客')
                self.登录后操作()
                # self.show()
            else:
                self.setWindowTitle('雨晨科技公司欢迎你！   ' + '当前是：游客模式')
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def tuichu(self):
        try:
            退出提示框 = QMessageBox.question(self, "提示", "退出系统", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

            if 退出提示框 == QMessageBox.Yes:
                self.close()
                qApp.quit()
                sys.exit(0)
            else:
                print('取消退出')
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def close_tab(self, index):  # 页面X绑定关闭
        try:
            # 得到选项卡栏中的选项卡的数量
            # self.tabWidget.count()

            # 获取当前选项卡对应的索引
            # self.tabWidget.currentIndex()

            # 获取索引位置的标题
            # self.tabWidget.tabText(index)

            # 标题列表 = []
            # for i in range(self.tabWidget.count()):
            # 	标题列表.append(self.tabWidget.tabText(i))
            #
            # 次数字典 = {}
            # for key in 标题列表:
            # 	次数字典[key] = 次数字典.get(key, 0) + 1
            #
            # if 次数字典['工作日志'] > 1 or self.tabWidget.tabText(index) not in ['工作日志', '综合查询']:
            # 	工具类.播放音乐(self.点击音效)
            # 	self.tabWidget.removeTab(index)

            self.tabWidget.removeTab(index)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def rizhikuang(self):
        try:
            if self.action_rzk.text() == '不显示日志框':
                self.action_rzk.setText('显示日志框')
                self.textEdit_gzrz.setFixedHeight(0)
            else:
                self.action_rzk.setText('不显示日志框')
                self.textEdit_gzrz.setFixedHeight(工具类.常量.主程序_日志框高度)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def add_shuxingshezhi(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.属性设置 = 属性设置(父窗口=self)
        self.tabWidget.addTab(self.属性设置, '属性设置')
        self.tabWidget.setCurrentWidget(self.属性设置)

    def add_changzhanweihu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.场站维护 = 场站维护(父窗口=self)
        self.tabWidget.addTab(self.场站维护, '场站维护')
        self.tabWidget.setCurrentWidget(self.场站维护)

    def add_yonghuguanli(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.用户管理 = 用户维护(父窗口=self)
        self.tabWidget.addTab(self.用户管理, '用户维护')
        self.tabWidget.setCurrentWidget(self.用户管理)

    def add_yungangtongdenglu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.登录 = 登录窗口(父窗口=self)
        self.登录.show()
        self.登录.setWindowModality(Qt.ApplicationModal)

    def add_chuanmingweihu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.船名维护 = 船名维护(父窗口=self)
        self.tabWidget.addTab(self.船名维护, '船名维护')
        self.tabWidget.setCurrentWidget(self.船名维护)

    def add_duoyangchaxun(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.多样查询 = 多样查询(父窗口=self)
        self.tabWidget.addTab(self.多样查询, '多样查询')
        self.tabWidget.setCurrentWidget(self.多样查询)

    def add_chuanqichaxun(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.船期查询 = 船期查询(父窗口=self)
        self.tabWidget.addTab(self.船期查询, '船期查询')
        self.tabWidget.setCurrentWidget(self.船期查询)

    def add_bugongzuozheng(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.补工作证 = 补工作证(父窗口=self)
        self.tabWidget.addTab(self.补工作证, '补工作证')
        self.tabWidget.setCurrentWidget(self.补工作证)

    def add_biaogegaizao(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.表格改造 = 表格改造(父窗口=self)
        self.tabWidget.addTab(self.表格改造, '表格改造')
        self.tabWidget.setCurrentWidget(self.表格改造)

    def add_jijiantongji(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.计件统计 = 计件统计(父窗口=self)
        self.tabWidget.addTab(self.计件统计, '计件统计')
        self.tabWidget.setCurrentWidget(self.计件统计)

    def add_zonghechaxun(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.综合查询 = 综合查询(父窗口=self)
        self.tabWidget.addTab(self.综合查询, '综合查询')
        self.tabWidget.setCurrentWidget(self.综合查询)

    def add_zuijinchuanqi(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.最近船期 = 最近船期(父窗口=self)
        self.tabWidget.addTab(self.最近船期, '最近船期')
        self.tabWidget.setCurrentWidget(self.最近船期)

    def add_jigangshijian(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.集港时间 = 集港时间(父窗口=self)
        self.tabWidget.addTab(self.集港时间, '集港时间')
        self.tabWidget.setCurrentWidget(self.集港时间)

    def add_waidianfanchang(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.外点返场 = 外点返场(父窗口=self)
        self.tabWidget.addTab(self.外点返场, '外点返场')
        self.tabWidget.setCurrentWidget(self.外点返场)

    def add_jigangchuchang(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.集港出场 = 集港出场(父窗口=self)
        self.tabWidget.addTab(self.集港出场, '集港出场')
        self.tabWidget.setCurrentWidget(self.集港出场)

    def add_chicunweihu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.尺寸维护 = 尺寸维护(父窗口=self)
        self.tabWidget.addTab(self.尺寸维护, '尺寸维护')
        self.tabWidget.setCurrentWidget(self.尺寸维护)

    def add_hangciweuhu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.航次维护 = 航次维护(父窗口=self)
        self.tabWidget.addTab(self.航次维护, '航次维护')
        self.tabWidget.setCurrentWidget(self.航次维护)

    def add_cheduiweihu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.车队维护 = 车队维护(父窗口=self)
        self.tabWidget.addTab(self.车队维护, '车队维护')
        self.tabWidget.setCurrentWidget(self.车队维护)

    def add_dongtaidaleiweihu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.动态大类维护 = 动态大类维护(父窗口=self)
        self.tabWidget.addTab(self.动态大类维护, '动态大类维护')
        self.tabWidget.setCurrentWidget(self.动态大类维护)

    def add_dongtaileixingweihu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.动态类型维护 = 动态类型维护(父窗口=self)
        self.tabWidget.addTab(self.动态类型维护, '动态类型维护')
        self.tabWidget.setCurrentWidget(self.动态类型维护)

    def add_xiangxingweihu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.箱型维护 = 箱型维护(父窗口=self)
        self.tabWidget.addTab(self.箱型维护, '箱型维护')
        self.tabWidget.setCurrentWidget(self.箱型维护)

    def add_xiangshuweihu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.箱属维护 = 箱属维护(父窗口=self)
        self.tabWidget.addTab(self.箱属维护, '箱属维护')
        self.tabWidget.setCurrentWidget(self.箱属维护)

    def add_kehuweihu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.客户维护 = 客户维护(父窗口=self)
        self.tabWidget.addTab(self.客户维护, '客户维护')
        self.tabWidget.setCurrentWidget(self.客户维护)

    def add_hangciweihu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.航次维护 = 航次维护(父窗口=self)
        self.tabWidget.addTab(self.航次维护, '航次维护')
        self.tabWidget.setCurrentWidget(self.航次维护)

    def add_feimuweihu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.费目维护 = 费目维护(父窗口=self)
        self.tabWidget.addTab(self.费目维护, '费目维护')
        self.tabWidget.setCurrentWidget(self.费目维护)

    def add_tuocheleixingweihu(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.拖车类型维护 = 拖车类型维护(父窗口=self)
        self.tabWidget.addTab(self.拖车类型维护, '拖车类型维护')
        self.tabWidget.setCurrentWidget(self.拖车类型维护)

    def add_chukouxiahuozhi(self, 是否有音效=True):

        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.出口下货纸 = 出口下货纸(父窗口=self)
        self.tabWidget.addTab(self.出口下货纸, '出口下货纸')
        self.tabWidget.setCurrentWidget(self.出口下货纸)

    def add_biquge(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.笔趣阁小说 = 笔趣阁小说(父窗口=self)
        self.tabWidget.addTab(self.笔趣阁小说, '笔趣阁小说')
        self.tabWidget.setCurrentWidget(self.笔趣阁小说)

    def add_kugouyinyue(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.酷狗音乐 = 酷狗音乐(父窗口=self)
        self.tabWidget.addTab(self.酷狗音乐, '酷狗音乐')
        self.tabWidget.setCurrentWidget(self.酷狗音乐)

    def add_quanxianshezhi(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.权限设置 = 权限设置(父窗口=self)
        self.tabWidget.addTab(self.权限设置, '权限设置')
        self.tabWidget.setCurrentWidget(self.权限设置)

    def add_cjglywh(self, 是否有音效=True):
        if 是否有音效:
            工具类.播放音乐(self.点击音效)
        self.超级管理员维护 = 超级管理员维护(父窗口=self)
        self.tabWidget.addTab(self.超级管理员维护, '超级管理员维护')
        self.tabWidget.setCurrentWidget(self.超级管理员维护)


class 登录窗口(QMainWindow, 模块包.登录窗口.Ui_MainWindow):
    bqshuangji = pyqtSignal()

    def __init__(self, 父窗口=None):
        try:
            super(登录窗口, self).__init__(父窗口)
            # 设置窗口模式：应用程序模式
            self.setWindowModality(Qt.ApplicationModal)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.数据库 = 父窗口.数据库 if 父窗口 else 数据库_mysql()
        self.网络 = 父窗口.网络 if 父窗口 else 网络连接()

        self.组件设计()
        self.事件绑定()

    def 组件设计(self):
        try:
            self.pushButton_3.close()
            self.pushButton_4.close()
            self.pushButton_5.close()
            self.comboBox.setFocusPolicy(Qt.StrongFocus)
            self.comboBox.setEditable(True)
            self.comboBox.pFilterModel = QSortFilterProxyModel(self.comboBox)
            self.comboBox.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
            self.comboBox.pFilterModel.setSourceModel(self.comboBox.model())
            self.comboBox.completer = QCompleter(self.comboBox.pFilterModel, self.comboBox)
            self.comboBox.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
            self.comboBox.setCompleter(self.comboBox.completer)
            self.comboBox.addItems(self.获取用户组())
            self.comboBox.setEditText("")
            self.更新验证码()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            self.comboBox.lineEdit().textEdited.connect(self.comboBox.pFilterModel.setFilterFixedString)
            self.comboBox.activated.connect(self.xllbxzxx)  # 下拉列表选中选项
            self.pushButton.clicked.connect(self.denglu)
            self.pushButton_2.clicked.connect(self.qingkong)
            self.label_4.mouseDoubleClickEvent = self.mouseDoubleClickEvent1
            self.bqshuangji.connect(self.zhitupian)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 更新验证码(self):
        try:
            二进制图片 = self.网络.获取图片()
            if 二进制图片.get('结果', False):
                with open('缓存\\验证码.png', "wb") as f:
                    f.write(二进制图片['数据'])
                self.label_4.setPixmap(QPixmap('缓存\\验证码.png'))
                self.statusbar.showMessage('验证码已更新！', 2000)
            else:
                self.label_4.setText('获取失败，请刷新！')
                self.statusbar.showMessage(二进制图片.get('原文', '未知原因'))
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)
            self.label_4.setText('验证码更新失败，请重试！')

    def 获取用户组(self):
        try:
            用户组 = self.数据库.查询数据('yonghu', 字段列表=['账号'])
            return [i[0] for i in 用户组]
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)
            return []

    def zhitupian(self):
        try:
            self.更新验证码()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def xllbxzxx(self):  # 下拉列表选中选项
        try:
            内容 = self.comboBox.currentText()
            用户组 = self.数据库.查询数据('yonghu', 字段列表=['密码'], 查询条件={'账号': 内容})
            if 用户组:
                self.lineEdit_2.setText(用户组[0][0])
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def denglu(self):
        try:
            if not self.comboBox.currentText():
                self.statusbar.showMessage('账号不能为空！！', 2000)
                return
            if not self.lineEdit_2.text():
                self.statusbar.showMessage('密码不能为空！！', 2000)
                return
            if not self.lineEdit_3.text():
                self.statusbar.showMessage('验证码不能为空！！', 2000)
                return

            登录值 = self.网络.登录(账号=self.comboBox.currentText(), 密码=self.lineEdit_2.text(),
                             验证码=self.lineEdit_3.text())
            if 登录值.get('结果', False):
                结果 = self.数据库.查询数据('yonghu', 字段列表=[], 查询条件={'账号': self.comboBox.currentText()})
                if not 结果:
                    self.数据库.插入数据('yonghu', 属性键列表=['账号', '密码'],
                                  属性值列表=[(self.comboBox.currentText(), self.lineEdit_2.text())])
                self.父窗口.登录后操作()
                self.父窗口.show()
                self.close()
            else:
                self.statusbar.showMessage(登录值.get('原文', '未知原因'))
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def mouseDoubleClickEvent1(self, a0: QtGui.QMouseEvent):
        try:
            self.bqshuangji.emit()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def qingkong(self):
        try:
            self.statusbar.showMessage('清空', 2000)
            self.comboBox.setCurrentText("")
            self.lineEdit_2.clear()
            self.lineEdit_3.clear()
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 笔趣阁小说(QMainWindow, 模块包.笔趣阁小说.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super(笔趣阁小说, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.数据库 = 父窗口.数据库 if 父窗口 else 数据库_mysql()
        self.网络 = 父窗口.网络 if 父窗口 else 网络连接()

        self.当前界面 = '小说表格界面'
        self.当前小说ID = '55'
        self.当前章节ID = '55'

        self.组件设计()
        self.事件绑定()

    def 组件设计(self):
        try:
            小说表格表头 = 工具类.常量.小说表格表头
            self.tableWidget_xs.setColumnCount(len(小说表格表头))
            self.tableWidget_xs.setHorizontalHeaderLabels(小说表格表头)
            self.tableWidget_xs.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
            self.tableWidget_xs.horizontalHeader().setStretchLastSection(True)

            章节表格表头 = 工具类.常量.章节表格表头
            self.tableWidget_zj.setColumnCount(len(章节表格表头))
            self.tableWidget_zj.setHorizontalHeaderLabels(章节表格表头)
            self.tableWidget_zj.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
            self.tableWidget_zj.horizontalHeader().setStretchLastSection(True)

            self.tableWidget_xs.setMaximumSize(40000, 30000)
            self.tableWidget_zj.setMaximumSize(40000, 0)
            self.textEdit_nr.setMaximumSize(40000, 0)

            self.label_zt.setMaximumSize(40000, 0)
            self.fontComboBox_zt.setMaximumSize(40000, 0)
            self.label_ztdx.setMaximumSize(40000, 0)
            self.lineEdit_ztdx.setMaximumSize(40000, 0)
            self.label_bjys.setMaximumSize(40000, 0)
            self.lineEdit_bjys.setMaximumSize(40000, 0)
            self.label_ztys.setMaximumSize(40000, 0)
            self.lineEdit_ztys.setMaximumSize(40000, 0)
            self.label_hjj.setMaximumSize(40000, 0)
            self.lineEdit_hjj.setMaximumSize(40000, 0)
            self.label_by.setMaximumSize(40000, 0)
            self.lineEdit_by.setMaximumSize(40000, 0)

            self.pushButton_fh.setEnabled(False)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            self.pushButton_ss.clicked.connect(self.sousuo)
            self.pushButton_fh.clicked.connect(self.jiemiankongzhi)
            # self.tableWidget_xs.cellDoubleClicked.connect(self.jinruzhangjei)  # 双击表格中的单元格，发出信号，并传递(行，列)
            # self.tableWidget_zj.cellDoubleClicked.connect(self.jinruneirong)  # 双击表格中的单元格，发出信号，并传递(行，列)
            self.tableWidget_xs.cellClicked.connect(self.jinruzhangjei)  # 单击表格中的单元格，发出信号，并传递(行，列)
            self.tableWidget_zj.cellClicked.connect(self.jinruneirong)  # 单击表格中的单元格，发出信号，并传递(行，列)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def sousuo(self):
        try:
            搜索内容 = self.lineEdit_nr.text()
            返回数据 = requests.get('http://www.gebiqu.com/modules/article/search.php?searchkey=' + 搜索内容)
            返回数据.encoding = 'utf-8'
            soup = BeautifulSoup(返回数据.text, "html.parser")
            小说 = {'内容': []}
            for i in soup.find_all('tr', id='nr'):
                单章小说 = {'小说名': i.td.a.text, '作者': i.find_all('td', attrs={"class": "odd"})[1].text,
                        '最新章节': i.find_all('td', attrs={"class": "even"})[0].text,
                        '字数': i.find_all('td', attrs={"class": "even"})[1].text}
                ks = i.td.a.attrs['href'].rfind('/')
                单章小说['ID'] = i.td.a.attrs['href'][ks + 1:-5]
                单章小说['打开'] = '打开'
                单章小说['下载'] = '下载'
                单章小说['进度'] = '进度'
                单章小说['最后更新时间'] = i.find('td', attrs={"align": "center", "class": "odd"}).text
                单章小说['状态'] = i.find('td', attrs={"align": "center", "class": "even"}).text
                小说['内容'].append(单章小说)
            # 小说={'内容': [{'小说名': '剑来', '作者': '烽火戏诸侯', '最新章节': '第一千一百二十八章 二十人与候补们（十）', '字数': '12256K', 'ID': '24950', '打开': '打开', '下载': '下载', '进度': '进度', '最后更新时间': '1694400847', '状态': '连载'}, {'小说名': '剑冢百年：一声剑来，天地皆惊', '作者': '田隶', '最新章节': '完结感言以及新书', '字数': '448K', 'ID': '262085', '打开': '打开', '下载': '下载', '进度': '进度', '最后更新时间': '1661864760', '状态': '连载'}, {'小说名': '剑来封天', '作者': '洗星辰', '最新章节': '第184章 一魔镇千州，怒问仙神何处有（下）', '字数': '474K', 'ID': '111546', '打开': '打开', '下载': '下载', '进度': '进度', '最后更新时间': '1538307889', '状态': '连载'}, {'小说名': '青冥等剑来', '作者': '剑来武心安', '最新章节': '第八十九章    退守', '字数': '597K', 'ID': '234800', '打开': '打开', '下载': '下载', '进度': '进度', '最后更新时间': '1612850498', '状态': '连载'}, {'小说名': '万界最强剑来系统', '作者': '哑舍', '最新章节': '请假条', '字数': '166K', 'ID': '224979', '打开': '打开', '下载': '下载', '进度': '进度', '最后更新时间': '1599804923', '状态': '连载'}, {'小说名': '心念剑来', '作者': '入梦之笔', '最新章节': '第七章 杀了他你会后悔的', '字数': '40K', 'ID': '190799', '打开': '打开', '下载': '下载', '进度': '进度', '最后更新时间': '1562390116', '状态': '连载'}, {'小说名': '开局选择天罚骨，自此踏上天骄路', '作者': '你也配剑来', '最新章节': '第62章 帝兵现天渊，星辰宝殿，深谷大帝墓', '字数': '80K', 'ID': '273818', '打开': '打开', '下载': '下载', '进度': '进度', '最后更新时间': '1679839140', '状态': '连载'}]}
            self.表格填充(小说, self.tableWidget_xs)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def jinruzhangjei(self, 行号, 列号):
        try:
            self.tableWidget_xs.setMaximumSize(40000, 0)
            self.tableWidget_zj.setMaximumSize(40000, 30000)
            self.textEdit_nr.setMaximumSize(40000, 0)

            self.label_zt.setMaximumSize(40000, 0)
            self.fontComboBox_zt.setMaximumSize(40000, 0)
            self.label_ztdx.setMaximumSize(40000, 0)
            self.lineEdit_ztdx.setMaximumSize(40000, 0)
            self.label_bjys.setMaximumSize(40000, 0)
            self.lineEdit_bjys.setMaximumSize(40000, 0)
            self.label_ztys.setMaximumSize(40000, 0)
            self.lineEdit_ztys.setMaximumSize(40000, 0)
            self.label_hjj.setMaximumSize(40000, 0)
            self.lineEdit_hjj.setMaximumSize(40000, 0)
            self.label_by.setMaximumSize(40000, 0)
            self.lineEdit_by.setMaximumSize(40000, 0)

            self.pushButton_ss.setEnabled(False)
            self.pushButton_fh.setEnabled(True)
            self.当前界面 = '章节表格界面'
            self.当前小说ID = self.tableWidget_xs.item(行号, 4).text()
            返回数据 = requests.get(f'http://www.gashuw.com/biquge_{self.当前小说ID}/')
            返回数据.encoding = 'utf-8'
            soup = BeautifulSoup(返回数据.text, "html.parser")
            章节 = {'内容': []}
            for i in soup.find_all('dd'):
                单章章节 = {'章节题目': i.a.text, '字数': '字数'}
                ks = i.a.attrs['href'].rfind('/')
                js = i.a.attrs['href'].rfind('.')
                单章章节['ID'] = i.a.attrs['href'][ks + 1:js]
                单章章节['打开'] = '打开'
                单章章节['下载'] = '下载'
                单章章节['进度'] = '进度'
                单章章节['备注'] = '备注'
                章节['内容'].append(单章章节)
            self.表格填充(章节, self.tableWidget_zj)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def jinruneirong(self, 行号, 列号):
        try:
            self.tableWidget_xs.setMaximumSize(40000, 0)
            self.tableWidget_zj.setMaximumSize(40000, 0)
            self.textEdit_nr.setMaximumSize(40000, 30000)

            self.label_zt.setMaximumSize(40000, 30000)
            self.fontComboBox_zt.setMaximumSize(40000, 30000)
            self.label_ztdx.setMaximumSize(40000, 30000)
            self.lineEdit_ztdx.setMaximumSize(40000, 30000)
            self.label_bjys.setMaximumSize(40000, 30000)
            self.lineEdit_bjys.setMaximumSize(40000, 30000)
            self.label_ztys.setMaximumSize(40000, 30000)
            self.lineEdit_ztys.setMaximumSize(40000, 30000)
            self.label_hjj.setMaximumSize(40000, 30000)
            self.lineEdit_hjj.setMaximumSize(40000, 30000)
            self.label_by.setMaximumSize(40000, 30000)
            self.lineEdit_by.setMaximumSize(40000, 30000)

            self.当前界面 = '内容文本框界面'
            self.当前章节ID = self.tableWidget_zj.item(行号, 3).text()
            返回数据 = requests.get(f'http://www.gashuw.com/biquge_{self.当前小说ID}/{self.当前章节ID}.html')
            返回数据.encoding = 'utf-8'
            soup = BeautifulSoup(返回数据.text, "html.parser")

            单章内容 = {'类型': '单章内容', '标题': soup.find('div', attrs={"class": "bookname"}).h1.text, '字数': '?????',
                    '更新时间': '????-??-?? ??:??:??'}
            内容 = soup.find('div', id="content").text

            单章内容['内容'] = 内容.replace(u'\xa0', ' ')

            self.文本框填充(单章内容, self.textEdit_nr)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def jiemiankongzhi(self):
        try:
            if self.当前界面 == '章节表格界面':
                self.tableWidget_xs.setMaximumSize(40000, 30000)
                self.tableWidget_zj.setMaximumSize(40000, 0)
                self.textEdit_nr.setMaximumSize(40000, 0)

                self.label_zt.setMaximumSize(40000, 0)
                self.fontComboBox_zt.setMaximumSize(40000, 0)
                self.label_ztdx.setMaximumSize(40000, 0)
                self.lineEdit_ztdx.setMaximumSize(40000, 0)
                self.label_bjys.setMaximumSize(40000, 0)
                self.lineEdit_bjys.setMaximumSize(40000, 0)
                self.label_ztys.setMaximumSize(40000, 0)
                self.lineEdit_ztys.setMaximumSize(40000, 0)
                self.label_hjj.setMaximumSize(40000, 0)
                self.lineEdit_hjj.setMaximumSize(40000, 0)
                self.label_by.setMaximumSize(40000, 0)
                self.lineEdit_by.setMaximumSize(40000, 0)
                self.pushButton_ss.setEnabled(True)
                self.pushButton_fh.setEnabled(False)

                self.pushButton_ss.setEnabled(True)
                self.pushButton_fh.setEnabled(False)
                self.当前界面 = '小说表格界面'
            elif self.当前界面 == '内容文本框界面':
                self.tableWidget_xs.setMaximumSize(40000, 0)
                self.tableWidget_zj.setMaximumSize(40000, 30000)
                self.textEdit_nr.setMaximumSize(40000, 0)
                self.label_zt.setMaximumSize(40000, 0)
                self.fontComboBox_zt.setMaximumSize(40000, 0)
                self.label_ztdx.setMaximumSize(40000, 0)
                self.lineEdit_ztdx.setMaximumSize(40000, 0)
                self.label_bjys.setMaximumSize(40000, 0)
                self.lineEdit_bjys.setMaximumSize(40000, 0)
                self.label_ztys.setMaximumSize(40000, 0)
                self.lineEdit_ztys.setMaximumSize(40000, 0)
                self.label_hjj.setMaximumSize(40000, 0)
                self.lineEdit_hjj.setMaximumSize(40000, 0)
                self.label_by.setMaximumSize(40000, 0)
                self.lineEdit_by.setMaximumSize(40000, 0)

                self.当前界面 = '章节表格界面'
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 文本框填充(self, 信息, 文本框组件):
        try:
            单章内容 = f'''{信息.get('标题', '第一章 剑来')}
            	字数：{str(信息.get('字数', '50'))}
            	更新时间：{信息.get('更新时间', '2023-8-23 05:06:23')}
            	{信息.get('内容', '内容')}
            				   '''
            文本框组件.setText(单章内容)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 表格填充(self, 信息, 表格组件):
        try:
            表格组件.setRowCount(len(信息['内容']))
            for i, 内容 in enumerate(信息['内容']):
                for j in range(表格组件.columnCount()):
                    单元格 = QTableWidgetItem(内容.get(表格组件.horizontalHeaderItem(j).text(), '暂无'))
                    单元格.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
                    表格组件.setItem(i, j, 单元格)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 酷狗音乐(QMainWindow, 模块包.酷狗音乐.Ui_MainWindow):

    def __init__(self, 父窗口=None):

        try:
            super(酷狗音乐, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.数据库 = 父窗口.数据库 if 父窗口 else 数据库_mysql()
        self.网络 = 父窗口.网络 if 父窗口 else 网络连接()

        self.组件设计()
        self.事件绑定()

    def 组件设计(self):
        try:
            pass
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            # tableWidget
            # lineEdit_nr
            # lineEdit_sm
            self.pushButton_ss.clicked.connect(self.sousuo)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def sousuo(self):
        try:
            搜索内容 = self.lineEdit_nr.text()
            print(搜索内容)
            # 网址 = f'https://c.y.qq.com/soso/fcgi-bin/client_search_cp?p=1&n=10&w={搜索内容}'
            # print(2)
            # aa = requests.get(网址)
            # print(3)
            # print(aa)
            # print(aa.text)
            ID = 'hjj'

            音乐 = 'https://u.y.qq.com/cgi-bin/musicu.fcg?data ={"req":{"module":"CDN.SrfCdnDispatchServer","method":"GetCdnDispatch","filename ":"M800","param ":{"guid":"8846039534 ","songmid":' + ID + ',"SONGTYPE":"[0]","uin":"1152921504784213523","loginflag":"1","platform":"20"}},"comm":{"uin":"1152921504784213523","format":"json","ct":"24" ,"cv":"0"}}'

            aa = requests.get(音乐)
            print(aa.text)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 权限设置(QMainWindow, 模块包.权限设置.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super(权限设置, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

        self.父窗口 = 父窗口
        self.数据库 = 父窗口.数据库 if 父窗口 else 数据库_mysql()
        self.网络 = 父窗口.网络 if 父窗口 else 网络连接()
        self.当前用户 = self.父窗口.当前用户
        self.权限组件 = {'用户维护': self.checkBox_0101,
                     '运港通登录': self.checkBox_0102,
                     '运港通快捷登录': self.checkBox_0103,
                     '综合查询': self.checkBox_0201,
                     '多样查询': self.checkBox_0202,
                     '船期查询': self.checkBox_0203,
                     '最近船期': self.checkBox_0204,
                     '集港时间': self.checkBox_0205,
                     '外点返场': self.checkBox_0301,
                     '集港出场': self.checkBox_0302,
                     '出口下货纸': self.checkBox_0303,
                     '补工作证': self.checkBox_0401,
                     '表格改造': self.checkBox_0402,
                     '计件统计': self.checkBox_0403,
                     '场站维护': self.checkBox_0501,
                     '尺寸维护': self.checkBox_0502,
                     '箱型维护': self.checkBox_0503,
                     '箱属维护': self.checkBox_0504,
                     '客户维护': self.checkBox_0505,
                     '航次维护': self.checkBox_0506,
                     '费目维护': self.checkBox_0507,
                     '车队维护': self.checkBox_0508,
                     '船名代码维护': self.checkBox_0509,
                     '动态类型维护': self.checkBox_0510,
                     '动态大类维护': self.checkBox_0511,
                     '拖车类型维护': self.checkBox_0512,
                     '超级管理员维护': self.checkBox_0513,
                     '笔趣阁': self.checkBox_0601,
                     '酷狗音乐': self.checkBox_0602,
                     '属性设置': self.checkBox_0701,
                     '权限设置': self.checkBox_0702,
                     '显示日志框': self.checkBox_0703}
        self.组件设置()
        self.事件绑定()

    def 组件设置(self):
        try:
            用户组 = self.数据库.查询数据('yonghu', 字段列表=['用户名'])
            用户组 = [""] + [i[0] for i in 用户组]
            self.comboBox_zhanghao.addItems(用户组)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 事件绑定(self):
        try:
            self.comboBox_zhanghao.currentTextChanged.connect(self.zhiquanxian)
            self.pushButton.clicked.connect(self.baocunquanxian)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def baocunquanxian(self):
        try:
            账号 = self.comboBox_zhanghao.currentText()
            if not 账号:
                self.statusbar.showMessage('需要设置的账号为空...')
                return
            权限 = {key: value.isChecked() for key, value in self.权限组件.items()}
            权限文本 = str(权限)
            if self.数据库.更新数据('yonghu', 更新字典={'权限': 权限文本},
                             更新条件={'用户名': self.comboBox_zhanghao.currentText()}):
                self.statusbar.showMessage(self.comboBox_zhanghao.currentText() + ' 权限更改完毕！')
            else:
                self.statusbar.showMessage(self.comboBox_zhanghao.currentText() + ' 权限更改失败....')
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def zhiquanxian(self):
        try:
            账号 = self.comboBox_zhanghao.currentText()
            if not 账号:
                for key in self.权限组件:
                    self.权限组件[key].setChecked(False)
                return
            权限文本 = self.数据库.查询数据('yonghu', 字段列表=['权限'], 查询条件={'用户名': 账号})
            if 权限文本 and 权限文本[0][0] not in ('0', 'R', ''):
                权限 = eval(权限文本[0][0])
            else:
                权限 = self.父窗口.默认权限
            for key, value in 权限.items():
                self.权限组件[key].setChecked(value)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


class 测试(QMainWindow, 模块包.测试.Ui_MainWindow):

    def __init__(self, 父窗口=None):
        try:
            super(测试, self).__init__(父窗口)
            self.setupUi(self)
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)

    def 组件设计(self):
        try:
            pass
        except Exception as e:
            工具类.logger.exception(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错,{e}")
            self.statusbar.showMessage(f"【{__class__.__name__}】中的<{sys._getframe().f_code.co_name}>出错", 2000)


主体代码行数 = sys._getframe().f_lineno  # 获取当前代码行的行号

状态 = 1
if 状态 == 1:
    if __name__ == "__main__":
        multiprocessing.freeze_support()
        app = QApplication(sys.argv)
        工具类.logger.info(
            f'-----工具类:< {工具类.工具类行数} >行代码, 主体:< {主体代码行数} >行代码, 一共:< {工具类.工具类行数 + 主体代码行数} >行代码。')
        主程序 = 主体程序(全局控制=app)
        sys.exit(app.exec_())
elif 状态 == 2:
    if __name__ == "__main__":
        multiprocessing.freeze_support()
        app = QApplication(sys.argv)
        工具类.logger.info(
            f'-----工具类:<{工具类.工具类行数}>行代码, 主体:<{主体代码行数}>行代码, 一共:<{工具类.工具类行数 + 主体代码行数}>行代码。')
        测试窗口 = 测试()
        测试窗口.show()
        sys.exit(app.exec_())